aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_protocols.h4
-rw-r--r--src/include/gnunet_psyc_service.h226
-rw-r--r--src/include/gnunet_psycstore_plugin.h41
-rw-r--r--src/include/gnunet_psycstore_service.h146
-rw-r--r--src/include/gnunet_social_service.h46
-rw-r--r--src/psyc/Makefile.am2
-rw-r--r--src/psyc/gnunet-service-psyc.c272
-rw-r--r--src/psyc/psyc.h57
-rw-r--r--src/psyc/psyc_api.c414
-rw-r--r--src/psyc/test_psyc.c348
-rw-r--r--src/psycstore/gnunet-service-psycstore.c97
-rw-r--r--src/psycstore/plugin_psycstore_sqlite.c238
-rw-r--r--src/psycstore/psycstore.h160
-rw-r--r--src/psycstore/psycstore_api.c309
-rw-r--r--src/psycstore/test_plugin_psycstore.c48
-rw-r--r--src/psycstore/test_psycstore.c65
-rw-r--r--src/social/gnunet-service-social.c16
-rw-r--r--src/social/social.h19
-rw-r--r--src/social/social_api.c43
19 files changed, 1938 insertions, 613 deletions
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 5626e1e5e..ea295197c 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2187,10 +2187,10 @@ extern "C"
2187/* 700 */ 2187/* 700 */
2188 2188
2189/** C->S: client requests channel history from PSYCstore. */ 2189/** C->S: client requests channel history from PSYCstore. */
2190#define GNUNET_MESSAGE_TYPE_PSYC_STORY_REQUEST 701 2190#define GNUNET_MESSAGE_TYPE_PSYC_HISTORY_REPLAY 701
2191 2191
2192/** S->C: result for a channel history request */ 2192/** S->C: result for a channel history request */
2193#define GNUNET_MESSAGE_TYPE_PSYC_STORY_RESULT 702 2193#define GNUNET_MESSAGE_TYPE_PSYC_HISTORY_RESULT 702
2194 2194
2195 2195
2196/** C->S: request best matching state variable from PSYCstore. */ 2196/** C->S: request best matching state variable from PSYCstore. */
diff --git a/src/include/gnunet_psyc_service.h b/src/include/gnunet_psyc_service.h
index 7097c46a8..25b405dad 100644
--- a/src/include/gnunet_psyc_service.h
+++ b/src/include/gnunet_psyc_service.h
@@ -160,6 +160,11 @@ enum GNUNET_PSYC_Policy
160enum GNUNET_PSYC_MessageFlags 160enum GNUNET_PSYC_MessageFlags
161{ 161{
162 /** 162 /**
163 * Default / no flags.
164 */
165 GNUNET_PSYC_MESSAGE_DEFAULT = 0,
166
167 /**
163 * Historic message, retrieved from PSYCstore. 168 * Historic message, retrieved from PSYCstore.
164 */ 169 */
165 GNUNET_PSYC_MESSAGE_HISTORIC = 1 << 0, 170 GNUNET_PSYC_MESSAGE_HISTORIC = 1 << 0,
@@ -314,12 +319,12 @@ struct GNUNET_PSYC_CountersResultMessage
314 /** 319 /**
315 * Status code for the operation. 320 * Status code for the operation.
316 */ 321 */
317 int32_t result_code GNUNET_PACKED; 322 uint32_t result_code GNUNET_PACKED;
318 323
319 /** 324 /**
320 * Last message ID sent to the channel. 325 * Last message ID sent to the channel.
321 */ 326 */
322 uint64_t max_message_id; 327 uint64_t max_message_id GNUNET_PACKED;
323}; 328};
324 329
325 330
@@ -503,13 +508,24 @@ struct GNUNET_PSYC_Master;
503 508
504 509
505/** 510/**
506 * Function called after the channel master started. 511 * Function called after connected to the PSYC service
512 * and the channel master started.
507 * 513 *
508 * @param cls Closure. 514 * Also called when reconnected to the service
509 * @param max_message_id Last message ID sent to the channel. 515 * after the connection closed unexpectedly.
516 *
517 * @param cls
518 * Closure.
519 * @param result
520 * #GNUNET_YES if there were already messages sent to the channel,
521 * #GNUNET_NO if the message history is empty,
522 * #GNUNET_SYSERR on error.
523 * @param max_message_id
524 * Last message ID sent to the channel.
510 */ 525 */
511typedef void 526typedef void
512(*GNUNET_PSYC_MasterStartCallback) (void *cls, uint64_t max_message_id); 527(*GNUNET_PSYC_MasterStartCallback) (void *cls, int result,
528 uint64_t max_message_id);
513 529
514 530
515/** 531/**
@@ -720,11 +736,21 @@ struct GNUNET_PSYC_Slave;
720/** 736/**
721 * Function called after the slave connected to the PSYC service. 737 * Function called after the slave connected to the PSYC service.
722 * 738 *
723 * @param cls Closure. 739 * Also called when reconnected to the service
724 * @param max_message_id Last message ID sent to the channel. 740 * after the connection closed unexpectedly.
741 *
742 * @param cls
743 * Closure.
744 * @param result
745 * #GNUNET_YES if there were already messages sent to the channel,
746 * #GNUNET_NO if the message history is empty,
747 * #GNUNET_SYSERR on error.
748 * @param max_message_id
749 * Last message ID sent to the channel.
725 */ 750 */
726typedef void 751typedef void
727(*GNUNET_PSYC_SlaveConnectCallback) (void *cls, uint64_t max_message_id); 752(*GNUNET_PSYC_SlaveConnectCallback) (void *cls, int result,
753 uint64_t max_message_id);
728 754
729 755
730/** 756/**
@@ -876,6 +902,23 @@ struct GNUNET_PSYC_Channel;
876 902
877 903
878/** 904/**
905 * Function called with the result of an asynchronous operation.
906 *
907 * @param cls
908 * Closure.
909 * @param result
910 * Result of the operation.
911 * Usually one of #GNUNET_OK, #GNUNET_YES, #GNUNET_NO, or #GNUNET_SYSERR.
912 * @param err_msg
913 * Error message.
914 */
915typedef void
916(*GNUNET_PSYC_ResultCallback) (void *cls,
917 int64_t result,
918 const char *err_msg);
919
920
921/**
879 * Convert a channel @a master to a @e channel handle to access the @e channel 922 * Convert a channel @a master to a @e channel handle to access the @e channel
880 * APIs. 923 * APIs.
881 * 924 *
@@ -921,7 +964,9 @@ void
921GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *channel, 964GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *channel,
922 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, 965 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
923 uint64_t announced_at, 966 uint64_t announced_at,
924 uint64_t effective_since); 967 uint64_t effective_since,
968 GNUNET_PSYC_ResultCallback result_cb,
969 void *cls);
925 970
926 971
927/** 972/**
@@ -949,7 +994,9 @@ void
949GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *channel, 994GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *channel,
950 const struct GNUNET_CRYPTO_EcdsaPublicKey 995 const struct GNUNET_CRYPTO_EcdsaPublicKey
951 *slave_key, 996 *slave_key,
952 uint64_t announced_at); 997 uint64_t announced_at,
998 GNUNET_PSYC_ResultCallback result_cb,
999 void *cls);
953 1000
954 1001
955/** 1002/**
@@ -962,74 +1009,69 @@ GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *channel,
962 * @param value_size Number of bytes in @a value. 1009 * @param value_size Number of bytes in @a value.
963 */ 1010 */
964typedef void 1011typedef void
965(*GNUNET_PSYC_StateCallback) (void *cls, 1012(*GNUNET_PSYC_StateVarCallback) (void *cls,
966 const char *name, 1013 const char *name,
967 const void *value, 1014 const void *value,
968 size_t value_size); 1015 size_t value_size);
969 1016
970 1017
971/** 1018/**
972 * Function called when a requested operation has finished. 1019 * Request to replay a part of the message history of the channel.
973 *
974 * @param cls Closure.
975 */
976typedef void
977(*GNUNET_PSYC_FinishCallback) (void *cls);
978
979
980/**
981 * Handle to a story telling operation.
982 */
983struct GNUNET_PSYC_Story;
984
985
986/**
987 * Request to be told the message history of the channel.
988 * 1020 *
989 * Historic messages (but NOT the state at the time) will be replayed (given to 1021 * Historic messages (but NOT the state at the time) will be replayed (given to
990 * the normal method handlers) if available and if access is permitted. 1022 * the normal method handlers) if available and if access is permitted.
991 * 1023 *
992 * To get the latest message, use 0 for both the start and end message ID. 1024 * @param channel
1025 * Which channel should be replayed?
1026 * @param start_message_id
1027 * Earliest interesting point in history.
1028 * @param end_message_id
1029 * Last (inclusive) interesting point in history.
1030 * @param finish_cb
1031 * Function to call when the requested history has been fully replayed
1032 * (counting message IDs might not suffice, as some messages might be
1033 * secret and thus the listener would not know the story is finished
1034 * without being told explicitly)o once this function has been called, the
1035 * client must not call GNUNET_PSYC_channel_history_replay_cancel() anymore.
1036 * @param cls
1037 * Closure for the callbacks.
993 * 1038 *
994 * @param channel Which channel should be replayed? 1039 * @return Handle to cancel history replay operation.
995 * @param start_message_id Earliest interesting point in history.
996 * @param end_message_id Last (exclusive) interesting point in history.
997 * @param message_cb Function to invoke on message parts received from the story.
998 * @param finish_cb Function to call when the requested story has been fully
999 * told (counting message IDs might not suffice, as some messages
1000 * might be secret and thus the listener would not know the story is
1001 * finished without being told explicitly); once this function
1002 * has been called, the client must not call
1003 * GNUNET_PSYC_channel_story_tell_cancel() anymore.
1004 * @param cls Closure for the callbacks.
1005 * @return Handle to cancel story telling operation.
1006 */ 1040 */
1007struct GNUNET_PSYC_Story * 1041void
1008GNUNET_PSYC_channel_story_tell (struct GNUNET_PSYC_Channel *channel, 1042GNUNET_PSYC_channel_history_replay (struct GNUNET_PSYC_Channel *channel,
1009 uint64_t start_message_id, 1043 uint64_t start_message_id,
1010 uint64_t end_message_id, 1044 uint64_t end_message_id,
1011 GNUNET_PSYC_MessageCallback message_cb, 1045 GNUNET_PSYC_ResultCallback finish_cb,
1012 GNUNET_PSYC_MessagePartCallback message_part_cb, 1046 void *cls);
1013 GNUNET_PSYC_FinishCallback finish_cb,
1014 void *cls);
1015 1047
1016 1048
1017/** 1049/**
1018 * Abort story telling. 1050 * Request to replay the latest messages from the message history of the channel.
1051 *
1052 * Historic messages (but NOT the state at the time) will be replayed (given to
1053 * the normal method handlers) if available and if access is permitted.
1019 * 1054 *
1020 * This function must not be called from within method handlers (as given to 1055 * @param channel
1021 * GNUNET_PSYC_slave_join()) of the slave. 1056 * Which channel should be replayed?
1057 * @param message_limit
1058 * Maximum number of messages to replay.
1059 * @param finish_cb
1060 * Function to call when the requested history has been fully replayed
1061 * (counting message IDs might not suffice, as some messages might be
1062 * secret and thus the listener would not know the story is finished
1063 * without being told explicitly)o once this function has been called, the
1064 * client must not call GNUNET_PSYC_channel_history_replay_cancel() anymore.
1065 * @param cls
1066 * Closure for the callbacks.
1022 * 1067 *
1023 * @param story Story telling operation to stop. 1068 * @return Handle to cancel history replay operation.
1024 */ 1069 */
1025void 1070void
1026GNUNET_PSYC_channel_story_tell_cancel (struct GNUNET_PSYC_Story *story); 1071GNUNET_PSYC_channel_history_replay_latest (struct GNUNET_PSYC_Channel *channel,
1027 1072 uint64_t message_limit,
1028 1073 GNUNET_PSYC_ResultCallback finish_cb,
1029/** 1074 void *cls);
1030 * Handle for a state query operation.
1031 */
1032struct GNUNET_PSYC_StateQuery;
1033 1075
1034 1076
1035/** 1077/**
@@ -1039,19 +1081,26 @@ struct GNUNET_PSYC_StateQuery;
1039 * less-specific name is matched; for example, requesting "_a_b" will match "_a" 1081 * less-specific name is matched; for example, requesting "_a_b" will match "_a"
1040 * if "_a_b" does not exist. 1082 * if "_a_b" does not exist.
1041 * 1083 *
1042 * @param channel Channel handle. 1084 * @param channel
1043 * @param full_name Full name of the requested variable, the actual variable 1085 * Channel handle.
1044 * returned might have a shorter name.. 1086 * @param full_name
1045 * @param cb Function called once when a matching state variable is found. 1087 * Full name of the requested variable.
1088 * The actual variable returned might have a shorter name.
1089 * @param var_cb
1090 * Function called once when a matching state variable is found.
1046 * Not called if there's no matching state variable. 1091 * Not called if there's no matching state variable.
1047 * @param cb_cls Closure for the callbacks. 1092 * @param result_cb
1048 * @return Handle that can be used to cancel the query operation. 1093 * Function called after the operation finished.
1094 * (i.e. all state variables have been returned via @a state_cb)
1095 * @param cls
1096 * Closure for the callbacks.
1049 */ 1097 */
1050struct GNUNET_PSYC_StateQuery * 1098void
1051GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel, 1099GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel,
1052 const char *full_name, 1100 const char *full_name,
1053 GNUNET_PSYC_StateCallback cb, 1101 GNUNET_PSYC_StateVarCallback var_cb,
1054 void *cb_cls); 1102 GNUNET_PSYC_ResultCallback result_cb,
1103 void *cls);
1055 1104
1056 1105
1057/** 1106/**
@@ -1064,26 +1113,25 @@ GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel,
1064 * The @a state_cb is invoked on all matching state variables asynchronously, as 1113 * The @a state_cb is invoked on all matching state variables asynchronously, as
1065 * the state is stored in and retrieved from the PSYCstore, 1114 * the state is stored in and retrieved from the PSYCstore,
1066 * 1115 *
1067 * @param channel Channel handle. 1116 * @param channel
1068 * @param name_prefix Prefix of the state variable name to match. 1117 * Channel handle.
1069 * @param cb Function to call with the matching state variables. 1118 * @param name_prefix
1070 * @param cb_cls Closure for the callbacks. 1119 * Prefix of the state variable name to match.
1071 * @return Handle that can be used to cancel the query operation. 1120 * @param var_cb
1121 * Function called once when a matching state variable is found.
1122 * Not called if there's no matching state variable.
1123 * @param result_cb
1124 * Function called after the operation finished.
1125 * (i.e. all state variables have been returned via @a state_cb)
1126 * @param cls
1127 * Closure for the callbacks.
1072 */ 1128 */
1073struct GNUNET_PSYC_StateQuery * 1129void
1074GNUNET_PSYC_channel_state_get_prefix (struct GNUNET_PSYC_Channel *channel, 1130GNUNET_PSYC_channel_state_get_prefix (struct GNUNET_PSYC_Channel *channel,
1075 const char *name_prefix, 1131 const char *name_prefix,
1076 GNUNET_PSYC_StateCallback cb, 1132 GNUNET_PSYC_StateVarCallback var_cb,
1077 void *cb_cls); 1133 GNUNET_PSYC_ResultCallback result_cb,
1078 1134 void *cls);
1079
1080/**
1081 * Cancel a state query operation.
1082 *
1083 * @param query Handle for the operation to cancel.
1084 */
1085void
1086GNUNET_PSYC_channel_state_get_cancel (struct GNUNET_PSYC_StateQuery *query);
1087 1135
1088 1136
1089#if 0 /* keep Emacsens' auto-indent happy */ 1137#if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/include/gnunet_psycstore_plugin.h b/src/include/gnunet_psycstore_plugin.h
index 1945b400e..3f02759f6 100644
--- a/src/include/gnunet_psycstore_plugin.h
+++ b/src/include/gnunet_psycstore_plugin.h
@@ -112,7 +112,7 @@ struct GNUNET_PSYCSTORE_PluginFunctions
112 uint64_t psycstore_flags); 112 uint64_t psycstore_flags);
113 113
114 /** 114 /**
115 * Retrieve a message fragment by fragment ID. 115 * Retrieve a message fragment range by fragment ID.
116 * 116 *
117 * @see GNUNET_PSYCSTORE_fragment_get() 117 * @see GNUNET_PSYCSTORE_fragment_get()
118 * 118 *
@@ -121,12 +121,29 @@ struct GNUNET_PSYCSTORE_PluginFunctions
121 int 121 int
122 (*fragment_get) (void *cls, 122 (*fragment_get) (void *cls,
123 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, 123 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
124 uint64_t fragment_id, 124 uint64_t first_fragment_id,
125 uint64_t last_fragment_id,
126 uint64_t *returned_fragments,
125 GNUNET_PSYCSTORE_FragmentCallback cb, 127 GNUNET_PSYCSTORE_FragmentCallback cb,
126 void *cb_cls); 128 void *cb_cls);
127 129
128 /** 130 /**
129 * Retrieve all fragments of a message. 131 * Retrieve latest message fragments.
132 *
133 * @see GNUNET_PSYCSTORE_fragment_get()
134 *
135 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
136 */
137 int
138 (*fragment_get_latest) (void *cls,
139 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
140 uint64_t fragment_limit,
141 uint64_t *returned_fragments,
142 GNUNET_PSYCSTORE_FragmentCallback cb,
143 void *cb_cls);
144
145 /**
146 * Retrieve all fragments of a message ID range.
130 * 147 *
131 * @see GNUNET_PSYCSTORE_message_get() 148 * @see GNUNET_PSYCSTORE_message_get()
132 * 149 *
@@ -135,12 +152,28 @@ struct GNUNET_PSYCSTORE_PluginFunctions
135 int 152 int
136 (*message_get) (void *cls, 153 (*message_get) (void *cls,
137 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, 154 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
138 uint64_t message_id, 155 uint64_t first_fragment_id,
156 uint64_t last_fragment_id,
139 uint64_t *returned_fragments, 157 uint64_t *returned_fragments,
140 GNUNET_PSYCSTORE_FragmentCallback cb, 158 GNUNET_PSYCSTORE_FragmentCallback cb,
141 void *cb_cls); 159 void *cb_cls);
142 160
143 /** 161 /**
162 * Retrieve all fragments of the latest messages.
163 *
164 * @see GNUNET_PSYCSTORE_message_get()
165 *
166 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
167 */
168 int
169 (*message_get_latest) (void *cls,
170 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
171 uint64_t fragment_limit,
172 uint64_t *returned_fragments,
173 GNUNET_PSYCSTORE_FragmentCallback cb,
174 void *cb_cls);
175
176 /**
144 * Retrieve a fragment of message specified by its message ID and fragment 177 * Retrieve a fragment of message specified by its message ID and fragment
145 * offset. 178 * offset.
146 * 179 *
diff --git a/src/include/gnunet_psycstore_service.h b/src/include/gnunet_psycstore_service.h
index 84d69c24d..78d016bb3 100644
--- a/src/include/gnunet_psycstore_service.h
+++ b/src/include/gnunet_psycstore_service.h
@@ -107,9 +107,10 @@ struct GNUNET_PSYCSTORE_OperationHandle;
107/** 107/**
108 * Function called with the result of an asynchronous operation. 108 * Function called with the result of an asynchronous operation.
109 * 109 *
110 * @param result #GNUNET_SYSERR on error, 110 * @param result
111 * #GNUNET_YES on success or if the peer was a member, 111 * #GNUNET_YES on success or if the peer was a member,
112 * #GNUNET_NO if the peer was not a member 112 * #GNUNET_NO if the peer was not a member,
113 * #GNUNET_SYSERR on error,
113 */ 114 */
114typedef void 115typedef void
115(*GNUNET_PSYCSTORE_ResultCallback) (void *cls, 116(*GNUNET_PSYCSTORE_ResultCallback) (void *cls,
@@ -235,7 +236,7 @@ typedef int
235 236
236 237
237/** 238/**
238 * Retrieve a message fragment by fragment ID. 239 * Retrieve message fragments by fragment ID range.
239 * 240 *
240 * @param h 241 * @param h
241 * Handle for the PSYCstore. 242 * Handle for the PSYCstore.
@@ -245,11 +246,15 @@ typedef int
245 * The slave requesting the fragment. If not NULL, a membership test is 246 * The slave requesting the fragment. If not NULL, a membership test is
246 * performed first and the fragment is only returned if the slave has 247 * performed first and the fragment is only returned if the slave has
247 * access to it. 248 * access to it.
248 * @param fragment_id 249 * @param first_fragment_id
249 * Fragment ID to retrieve. Use 0 to get the latest message fragment. 250 * First fragment ID to retrieve.
250 * @param fcb 251 * Use 0 to get the latest message fragment.
252 * @param last_fragment_id
253 * Last consecutive fragment ID to retrieve.
254 * Use 0 to get the latest message fragment.
255 * @param fragment_cb
251 * Callback to call with the retrieved fragments. 256 * Callback to call with the retrieved fragments.
252 * @param rcb 257 * @param result_cb
253 * Callback to call with the result of the operation. 258 * Callback to call with the result of the operation.
254 * @param cls 259 * @param cls
255 * Closure for the callbacks. 260 * Closure for the callbacks.
@@ -260,14 +265,53 @@ struct GNUNET_PSYCSTORE_OperationHandle *
260GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h, 265GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h,
261 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, 266 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
262 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, 267 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
263 uint64_t fragment_id, 268 uint64_t first_message_id,
264 GNUNET_PSYCSTORE_FragmentCallback fcb, 269 uint64_t last_message_id,
265 GNUNET_PSYCSTORE_ResultCallback rcb, 270 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
271 GNUNET_PSYCSTORE_ResultCallback result_cb,
266 void *cls); 272 void *cls);
267 273
268 274
269/** 275/**
270 * Retrieve all fragments of a message. 276 * Retrieve latest message fragments.
277 *
278 * @param h
279 * Handle for the PSYCstore.
280 * @param channel_key
281 * The channel we are interested in.
282 * @param slave_key
283 * The slave requesting the fragment. If not NULL, a membership test is
284 * performed first and the fragment is only returned if the slave has
285 * access to it.
286 * @param first_fragment_id
287 * First fragment ID to retrieve.
288 * Use 0 to get the latest message fragment.
289 * @param last_fragment_id
290 * Last consecutive fragment ID to retrieve.
291 * Use 0 to get the latest message fragment.
292 * @param fragment_limit
293 * Maximum number of fragments to retrieve.
294 * @param fragment_cb
295 * Callback to call with the retrieved fragments.
296 * @param rcb
297 * Callback to call with the result of the operation.
298 * @param cls
299 * Closure for the callbacks.
300 *
301 * @return Handle that can be used to cancel the operation.
302 */
303struct GNUNET_PSYCSTORE_OperationHandle *
304GNUNET_PSYCSTORE_fragment_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
305 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
306 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
307 uint64_t fragment_limit,
308 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
309 GNUNET_PSYCSTORE_ResultCallback rcb,
310 void *cls);
311
312
313/**
314 * Retrieve all fragments of messages in a message ID range.
271 * 315 *
272 * @param h 316 * @param h
273 * Handle for the PSYCstore. 317 * Handle for the PSYCstore.
@@ -277,11 +321,15 @@ GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h,
277 * The slave requesting the message. If not NULL, a membership test is 321 * The slave requesting the message. If not NULL, a membership test is
278 * performed first and the message is only returned if the slave has 322 * performed first and the message is only returned if the slave has
279 * access to it. 323 * access to it.
280 * @param message_id 324 * @param first_message_id
281 * Message ID to retrieve. Use 0 to get the latest message. 325 * First message ID to retrieve.
282 * @param fcb 326 * Use 0 to get the latest message.
327 * @param last_message_id
328 * Last consecutive message ID to retrieve.
329 * Use 0 to get the latest message.
330 * @param fragment_cb
283 * Callback to call with the retrieved fragments. 331 * Callback to call with the retrieved fragments.
284 * @param rcb 332 * @param result_cb
285 * Callback to call with the result of the operation. 333 * Callback to call with the result of the operation.
286 * @param cls 334 * @param cls
287 * Closure for the callbacks. 335 * Closure for the callbacks.
@@ -292,23 +340,67 @@ struct GNUNET_PSYCSTORE_OperationHandle *
292GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h, 340GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
293 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, 341 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
294 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, 342 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
295 uint64_t message_id, 343 uint64_t first_message_id,
296 GNUNET_PSYCSTORE_FragmentCallback fcb, 344 uint64_t last_message_id,
297 GNUNET_PSYCSTORE_ResultCallback rcb, 345 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
346 GNUNET_PSYCSTORE_ResultCallback result_cb,
298 void *cls); 347 void *cls);
299 348
300 349
301/** 350/**
351 * Retrieve all fragments of the latest messages.
352 *
353 * @param h
354 * Handle for the PSYCstore.
355 * @param channel_key
356 * The channel we are interested in.
357 * @param slave_key
358 * The slave requesting the message. If not NULL, a membership test is
359 * performed first and the message is only returned if the slave has
360 * access to it.
361 * @param message_limit
362 * Maximum number of messages to retrieve.
363 * @param fragment_cb
364 * Callback to call with the retrieved fragments.
365 * @param rcb
366 * Callback to call with the result of the operation.
367 * @param cls
368 * Closure for the callbacks.
369 *
370 * @return Handle that can be used to cancel the operation.
371 */
372struct GNUNET_PSYCSTORE_OperationHandle *
373GNUNET_PSYCSTORE_message_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
374 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
375 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
376 uint64_t message_limit,
377 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
378 GNUNET_PSYCSTORE_ResultCallback rcb,
379 void *cls);
380
381
382/**
302 * Retrieve a fragment of message specified by its message ID and fragment 383 * Retrieve a fragment of message specified by its message ID and fragment
303 * offset. 384 * offset.
304 * 385 *
305 * @param h Handle for the PSYCstore. 386 * @param h
306 * @param channel_key The channel we are interested in. 387 * Handle for the PSYCstore.
307 * @param message_id Message ID to check. Use 0 to get the latest message. 388 * @param channel_key
308 * @param fragment_offset Offset of the fragment to retrieve. 389 * The channel we are interested in.
309 * @param fcb Callback to call with the retrieved fragments. 390 * @param slave_key
310 * @param rcb Callback to call with the result of the operation. 391 * The slave requesting the message fragment. If not NULL, a membership
311 * @param cls Closure for the callbacks. 392 * test is performed first and the message fragment is only returned
393 * if the slave has access to it.
394 * @param message_id
395 * Message ID to retrieve. Use 0 to get the latest message.
396 * @param fragment_offset
397 * Offset of the fragment to retrieve.
398 * @param fragment_cb
399 * Callback to call with the retrieved fragments.
400 * @param result_cb
401 * Callback to call with the result of the operation.
402 * @param cls
403 * Closure for the callbacks.
312 * 404 *
313 * @return Handle that can be used to cancel the operation. 405 * @return Handle that can be used to cancel the operation.
314 */ 406 */
@@ -318,8 +410,8 @@ GNUNET_PSYCSTORE_message_get_fragment (struct GNUNET_PSYCSTORE_Handle *h,
318 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, 410 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
319 uint64_t message_id, 411 uint64_t message_id,
320 uint64_t fragment_offset, 412 uint64_t fragment_offset,
321 GNUNET_PSYCSTORE_FragmentCallback fcb, 413 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
322 GNUNET_PSYCSTORE_ResultCallback rcb, 414 GNUNET_PSYCSTORE_ResultCallback result_cb,
323 void *cls); 415 void *cls);
324 416
325 417
diff --git a/src/include/gnunet_social_service.h b/src/include/gnunet_social_service.h
index ca1578820..66427a072 100644
--- a/src/include/gnunet_social_service.h
+++ b/src/include/gnunet_social_service.h
@@ -287,12 +287,18 @@ typedef void
287/** 287/**
288 * Function called after the host entered the place. 288 * Function called after the host entered the place.
289 * 289 *
290 * @param cls Closure. 290 * @param cls
291 * @param max_message_id Last message ID sent to the channel. 291 * Closure.
292 * Or 0 if no messages have been sent to the place yet. 292 * @param result
293 * #GNUNET_OK on success, or
294 * #GNUNET_SYSERR on error.
295 * @param max_message_id
296 * Last message ID sent to the channel.
297 * Or 0 if no messages have been sent to the place yet.
293 */ 298 */
294typedef void 299typedef void
295(*GNUNET_SOCIAL_HostEnterCallback) (void *cls, uint64_t max_message_id); 300(*GNUNET_SOCIAL_HostEnterCallback) (void *cls, int result,
301 uint64_t max_message_id);
296 302
297 303
298/** 304/**
@@ -793,18 +799,22 @@ struct GNUNET_SOCIAL_WatchHandle;
793/** 799/**
794 * Watch a place for changed objects. 800 * Watch a place for changed objects.
795 * 801 *
796 * @param place Place to watch. 802 * @param place
797 * @param object_filter Object prefix to match. 803 * Place to watch.
798 * @param state_cb Function to call when an object/state changes. 804 * @param object_filter
799 * @param state_cb_cls Closure for callback. 805 * Object prefix to match.
806 * @param state_var_cb
807 * Function to call when an object/state var changes.
808 * @param cls
809 * Closure for callback.
800 * 810 *
801 * @return Handle that can be used to cancel watching. 811 * @return Handle that can be used to cancel watching.
802 */ 812 */
803struct GNUNET_SOCIAL_WatchHandle * 813struct GNUNET_SOCIAL_WatchHandle *
804GNUNET_SOCIAL_place_watch (struct GNUNET_SOCIAL_Place *place, 814GNUNET_SOCIAL_place_watch (struct GNUNET_SOCIAL_Place *place,
805 const char *object_filter, 815 const char *object_filter,
806 GNUNET_PSYC_StateCallback state_cb, 816 GNUNET_PSYC_StateVarCallback state_var_cb,
807 void *state_cb_cls); 817 void *cls);
808 818
809 819
810/** 820/**
@@ -822,18 +832,22 @@ struct GNUNET_SOCIAL_LookHandle;
822/** 832/**
823 * Look at objects in the place with a matching name prefix. 833 * Look at objects in the place with a matching name prefix.
824 * 834 *
825 * @param place The place to look its objects at. 835 * @param place
826 * @param name_prefix Look at objects with names beginning with this value. 836 * The place to look its objects at.
827 * @param state_cb Function to call for each object found. 837 * @param name_prefix
828 * @param state_cb_cls Closure for callback function. 838 * Look at objects with names beginning with this value.
839 * @param state_var_cb
840 * Function to call for each object found.
841 * @param cls
842 * Closure for callback function.
829 * 843 *
830 * @return Handle that can be used to stop looking at objects. 844 * @return Handle that can be used to stop looking at objects.
831 */ 845 */
832struct GNUNET_SOCIAL_LookHandle * 846struct GNUNET_SOCIAL_LookHandle *
833GNUNET_SOCIAL_place_look (struct GNUNET_SOCIAL_Place *place, 847GNUNET_SOCIAL_place_look (struct GNUNET_SOCIAL_Place *place,
834 const char *name_prefix, 848 const char *name_prefix,
835 GNUNET_PSYC_StateCallback state_cb, 849 GNUNET_PSYC_StateVarCallback state_var_cb,
836 void *state_cb_cls); 850 void *cls);
837 851
838 852
839/** 853/**
diff --git a/src/psyc/Makefile.am b/src/psyc/Makefile.am
index b18605ab9..fb4341751 100644
--- a/src/psyc/Makefile.am
+++ b/src/psyc/Makefile.am
@@ -86,12 +86,14 @@ test_psyc_LDADD = \
86 libgnunetpsyc.la \ 86 libgnunetpsyc.la \
87 libgnunetpsycutil.la \ 87 libgnunetpsycutil.la \
88 $(top_builddir)/src/testing/libgnunettesting.la \ 88 $(top_builddir)/src/testing/libgnunettesting.la \
89 $(top_builddir)/src/core/libgnunetcore.la \
89 $(top_builddir)/src/env/libgnunetenv.la \ 90 $(top_builddir)/src/env/libgnunetenv.la \
90 $(top_builddir)/src/util/libgnunetutil.la 91 $(top_builddir)/src/util/libgnunetutil.la
91test_psyc_DEPENDENCIES = \ 92test_psyc_DEPENDENCIES = \
92 libgnunetpsyc.la \ 93 libgnunetpsyc.la \
93 libgnunetpsycutil.la \ 94 libgnunetpsycutil.la \
94 $(top_builddir)/src/testing/libgnunettesting.la \ 95 $(top_builddir)/src/testing/libgnunettesting.la \
96 $(top_builddir)/src/core/libgnunetcore.la \
95 $(top_builddir)/src/env/libgnunetenv.la \ 97 $(top_builddir)/src/env/libgnunetenv.la \
96 $(top_builddir)/src/util/libgnunetutil.la 98 $(top_builddir)/src/util/libgnunetutil.la
97 99
diff --git a/src/psyc/gnunet-service-psyc.c b/src/psyc/gnunet-service-psyc.c
index e7020bc69..3adc34d2a 100644
--- a/src/psyc/gnunet-service-psyc.c
+++ b/src/psyc/gnunet-service-psyc.c
@@ -402,6 +402,14 @@ struct Slave
402}; 402};
403 403
404 404
405struct OperationClosure
406{
407 struct GNUNET_SERVER_Client *client;
408 struct Channel *chn;
409 uint64_t op_id;
410};
411
412
405static void 413static void
406transmit_message (struct Channel *chn); 414transmit_message (struct Channel *chn);
407 415
@@ -585,6 +593,46 @@ client_send_msg (const struct Channel *chn,
585 593
586 594
587/** 595/**
596 * Send a result code back to the client.
597 *
598 * @param client
599 * Client that should receive the result code.
600 * @param result_code
601 * Code to transmit.
602 * @param op_id
603 * Operation ID in network byte order.
604 * @param err_msg
605 * Error message to include (or NULL for none).
606 */
607static void
608client_send_result (struct GNUNET_SERVER_Client *client, uint64_t op_id,
609 int64_t result_code, const char *err_msg)
610{
611 struct OperationResult *res;
612 size_t err_len = 0; // FIXME: maximum length
613
614 if (NULL != err_msg)
615 err_len = strlen (err_msg) + 1;
616 res = GNUNET_malloc (sizeof (struct OperationResult) + err_len);
617 res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE);
618 res->header.size = htons (sizeof (struct OperationResult) + err_len);
619 res->result_code = GNUNET_htonll (result_code + INT64_MAX + 1);
620 res->op_id = op_id;
621 if (0 < err_len)
622 memcpy (&res[1], err_msg, err_len);
623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
624 "%p Sending result to client for operation #%" PRIu64 ": "
625 "%" PRId64 " (%s)\n",
626 client, GNUNET_ntohll (op_id), result_code, err_msg);
627
628 GNUNET_SERVER_notification_context_add (nc, client);
629 GNUNET_SERVER_notification_context_unicast (nc, client, &res->header,
630 GNUNET_NO);
631 GNUNET_free (res);
632}
633
634
635/**
588 * Closure for join_mem_test_cb() 636 * Closure for join_mem_test_cb()
589 */ 637 */
590struct JoinMemTestClosure 638struct JoinMemTestClosure
@@ -799,7 +847,8 @@ mcast_recv_replay_fragment (void *cls,
799 847
800{ 848{
801 struct Channel *chn = cls; 849 struct Channel *chn = cls;
802 GNUNET_PSYCSTORE_fragment_get (store, &chn->pub_key, slave_key, fragment_id, 850 GNUNET_PSYCSTORE_fragment_get (store, &chn->pub_key, slave_key,
851 fragment_id, fragment_id,
803 &store_recv_fragment_replay, 852 &store_recv_fragment_replay,
804 &store_recv_fragment_replay_result, rh); 853 &store_recv_fragment_replay_result, rh);
805} 854}
@@ -817,7 +866,8 @@ mcast_recv_replay_message (void *cls,
817 struct GNUNET_MULTICAST_ReplayHandle *rh) 866 struct GNUNET_MULTICAST_ReplayHandle *rh)
818{ 867{
819 struct Channel *chn = cls; 868 struct Channel *chn = cls;
820 GNUNET_PSYCSTORE_message_get (store, &chn->pub_key, slave_key, message_id, 869 GNUNET_PSYCSTORE_message_get (store, &chn->pub_key, slave_key,
870 message_id, message_id,
821 &store_recv_fragment_replay, 871 &store_recv_fragment_replay,
822 &store_recv_fragment_replay_result, rh); 872 &store_recv_fragment_replay_result, rh);
823} 873}
@@ -865,7 +915,8 @@ hash_key_from_hll (struct GNUNET_HashCode *key, uint64_t n)
865 */ 915 */
866static void 916static void
867client_send_mcast_msg (struct Channel *chn, 917client_send_mcast_msg (struct Channel *chn,
868 const struct GNUNET_MULTICAST_MessageHeader *mmsg) 918 const struct GNUNET_MULTICAST_MessageHeader *mmsg,
919 uint32_t flags)
869{ 920{
870 struct GNUNET_PSYC_MessageHeader *pmsg; 921 struct GNUNET_PSYC_MessageHeader *pmsg;
871 uint16_t size = ntohs (mmsg->header.size); 922 uint16_t size = ntohs (mmsg->header.size);
@@ -882,6 +933,7 @@ client_send_mcast_msg (struct Channel *chn,
882 pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); 933 pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE);
883 pmsg->message_id = mmsg->message_id; 934 pmsg->message_id = mmsg->message_id;
884 pmsg->fragment_offset = mmsg->fragment_offset; 935 pmsg->fragment_offset = mmsg->fragment_offset;
936 pmsg->flags = htonl (flags);
885 937
886 memcpy (&pmsg[1], &mmsg[1], size - sizeof (*mmsg)); 938 memcpy (&pmsg[1], &mmsg[1], size - sizeof (*mmsg));
887 client_send_msg (chn, &pmsg->header); 939 client_send_msg (chn, &pmsg->header);
@@ -1111,7 +1163,7 @@ fragment_queue_run (struct Channel *chn, uint64_t msg_id,
1111 { 1163 {
1112 if (GNUNET_NO == drop) 1164 if (GNUNET_NO == drop)
1113 { 1165 {
1114 client_send_mcast_msg (chn, cache_entry->mmsg); 1166 client_send_mcast_msg (chn, cache_entry->mmsg, 0);
1115 } 1167 }
1116 if (cache_entry->ref_count <= 1) 1168 if (cache_entry->ref_count <= 1)
1117 { 1169 {
@@ -1375,10 +1427,10 @@ store_recv_master_counters (void *cls, int result, uint64_t max_fragment_id,
1375 struct Channel *chn = &mst->chn; 1427 struct Channel *chn = &mst->chn;
1376 chn->store_op = NULL; 1428 chn->store_op = NULL;
1377 1429
1378 struct CountersResult res; 1430 struct GNUNET_PSYC_CountersResultMessage res;
1379 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK); 1431 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK);
1380 res.header.size = htons (sizeof (res)); 1432 res.header.size = htons (sizeof (res));
1381 res.result_code = htonl (result); 1433 res.result_code = htonl (result - INT32_MIN);
1382 res.max_message_id = GNUNET_htonll (max_message_id); 1434 res.max_message_id = GNUNET_htonll (max_message_id);
1383 1435
1384 if (GNUNET_OK == result || GNUNET_NO == result) 1436 if (GNUNET_OK == result || GNUNET_NO == result)
@@ -1421,10 +1473,10 @@ store_recv_slave_counters (void *cls, int result, uint64_t max_fragment_id,
1421 struct Channel *chn = &slv->chn; 1473 struct Channel *chn = &slv->chn;
1422 chn->store_op = NULL; 1474 chn->store_op = NULL;
1423 1475
1424 struct CountersResult res; 1476 struct GNUNET_PSYC_CountersResultMessage res;
1425 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK); 1477 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK);
1426 res.header.size = htons (sizeof (res)); 1478 res.header.size = htons (sizeof (res));
1427 res.result_code = htonl (result); 1479 res.result_code = htonl (result - INT32_MIN);
1428 res.max_message_id = GNUNET_htonll (max_message_id); 1480 res.max_message_id = GNUNET_htonll (max_message_id);
1429 1481
1430 if (GNUNET_OK == result || GNUNET_NO == result) 1482 if (GNUNET_OK == result || GNUNET_NO == result)
@@ -1511,10 +1563,10 @@ client_recv_master_start (void *cls, struct GNUNET_SERVER_Client *client,
1511 { 1563 {
1512 chn = &mst->chn; 1564 chn = &mst->chn;
1513 1565
1514 struct CountersResult res; 1566 struct GNUNET_PSYC_CountersResultMessage res;
1515 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK); 1567 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK);
1516 res.header.size = htons (sizeof (res)); 1568 res.header.size = htons (sizeof (res));
1517 res.result_code = htonl (GNUNET_OK); 1569 res.result_code = htonl ((uint32_t) GNUNET_OK + INT32_MIN);
1518 res.max_message_id = GNUNET_htonll (mst->max_message_id); 1570 res.max_message_id = GNUNET_htonll (mst->max_message_id);
1519 1571
1520 GNUNET_SERVER_notification_context_add (nc, client); 1572 GNUNET_SERVER_notification_context_add (nc, client);
@@ -1621,10 +1673,10 @@ client_recv_slave_join (void *cls, struct GNUNET_SERVER_Client *client,
1621 { 1673 {
1622 chn = &slv->chn; 1674 chn = &slv->chn;
1623 1675
1624 struct CountersResult res; 1676 struct GNUNET_PSYC_CountersResultMessage res;
1625 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK); 1677 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK);
1626 res.header.size = htons (sizeof (res)); 1678 res.header.size = htons (sizeof (res));
1627 res.result_code = htonl (GNUNET_OK); 1679 res.result_code = htonl ((uint32_t) GNUNET_OK - INT32_MIN);
1628 res.max_message_id = GNUNET_htonll (chn->max_message_id); 1680 res.max_message_id = GNUNET_htonll (chn->max_message_id);
1629 1681
1630 GNUNET_SERVER_notification_context_add (nc, client); 1682 GNUNET_SERVER_notification_context_add (nc, client);
@@ -2047,17 +2099,26 @@ client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client,
2047}; 2099};
2048 2100
2049 2101
2102struct MembershipStoreClosure
2103{
2104 struct GNUNET_SERVER_Client *client;
2105 struct Channel *chn;
2106 uint64_t op_id;
2107};
2108
2109
2050/** 2110/**
2051 * Received result of GNUNET_PSYCSTORE_membership_store() 2111 * Received result of GNUNET_PSYCSTORE_membership_store()
2052 */ 2112 */
2053static void 2113static void
2054store_recv_membership_store_result (void *cls, int64_t result, const char *err_msg) 2114store_recv_membership_store_result (void *cls, int64_t result, const char *err_msg)
2055{ 2115{
2056 struct GNUNET_MULTICAST_MembershipTestHandle *mth = cls; 2116 struct MembershipStoreClosure *mcls = cls;
2057 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2058 "%p GNUNET_PSYCSTORE_membership_store() returned %" PRId64 " (%s)\n", 2118 "%p GNUNET_PSYCSTORE_membership_store() returned %" PRId64 " (%s)\n",
2059 mth, result, err_msg); 2119 mcls->chn, result, err_msg);
2060 /* FIXME: send result to client */ 2120
2121 client_send_result (mcls->client, mcls->op_id, result, err_msg);
2061} 2122}
2062 2123
2063 2124
@@ -2075,6 +2136,11 @@ client_recv_membership_store (void *cls, struct GNUNET_SERVER_Client *client,
2075 const struct ChannelMembershipStoreRequest * 2136 const struct ChannelMembershipStoreRequest *
2076 req = (const struct ChannelMembershipStoreRequest *) msg; 2137 req = (const struct ChannelMembershipStoreRequest *) msg;
2077 2138
2139 struct MembershipStoreClosure *mcls = GNUNET_malloc (sizeof (*mcls));
2140 mcls->client = client;
2141 mcls->chn = chn;
2142 mcls->op_id = req->op_id;
2143
2078 uint64_t announced_at = GNUNET_ntohll (req->announced_at); 2144 uint64_t announced_at = GNUNET_ntohll (req->announced_at);
2079 uint64_t effective_since = GNUNET_ntohll (req->effective_since); 2145 uint64_t effective_since = GNUNET_ntohll (req->effective_since);
2080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2086,19 +2152,138 @@ client_recv_membership_store (void *cls, struct GNUNET_SERVER_Client *client,
2086 GNUNET_PSYCSTORE_membership_store (store, &chn->pub_key, &req->slave_key, 2152 GNUNET_PSYCSTORE_membership_store (store, &chn->pub_key, &req->slave_key,
2087 req->did_join, announced_at, effective_since, 2153 req->did_join, announced_at, effective_since,
2088 0, /* FIXME: group_generation */ 2154 0, /* FIXME: group_generation */
2089 &store_recv_membership_store_result, chn); 2155 &store_recv_membership_store_result, mcls);
2090 GNUNET_SERVER_receive_done (client, GNUNET_OK); 2156 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2091} 2157}
2092 2158
2093 2159
2160static int
2161store_recv_fragment_history (void *cls,
2162 struct GNUNET_MULTICAST_MessageHeader *msg,
2163 enum GNUNET_PSYCSTORE_MessageFlags flags)
2164{
2165 struct OperationClosure *opcls = cls;
2166 struct Channel *chn = opcls->chn;
2167 client_send_mcast_msg (chn, msg, GNUNET_PSYC_MESSAGE_HISTORIC);
2168 return GNUNET_YES;
2169}
2170
2171
2172/**
2173 * Received result of GNUNET_PSYCSTORE_fragment_get() for multicast replay.
2174 */
2175static void
2176store_recv_fragment_history_result (void *cls, int64_t result, const char *err_msg)
2177{
2178 struct OperationClosure *opcls = cls;
2179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2180 "%p History replay #%" PRIu64 ": "
2181 "PSYCSTORE returned %" PRId64 " (%s)\n",
2182 opcls->chn, opcls->op_id, result, err_msg);
2183
2184 client_send_result (opcls->client, opcls->op_id, result, err_msg);
2185}
2186
2187
2094/** 2188/**
2095 * Client requests channel history from PSYCstore. 2189 * Client requests channel history from PSYCstore.
2096 */ 2190 */
2097static void 2191static void
2098client_recv_story_request (void *cls, struct GNUNET_SERVER_Client *client, 2192client_recv_history_replay (void *cls, struct GNUNET_SERVER_Client *client,
2099 const struct GNUNET_MessageHeader *msg) 2193 const struct GNUNET_MessageHeader *msg)
2194{
2195 struct Channel *
2196 chn = GNUNET_SERVER_client_get_user_context (client, struct Channel);
2197 GNUNET_assert (NULL != chn);
2198
2199 const struct HistoryRequest *
2200 req = (const struct HistoryRequest *) msg;
2201
2202 struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
2203 opcls->client = client;
2204 opcls->chn = chn;
2205 opcls->op_id = req->op_id;
2206
2207 if (0 == req->message_limit)
2208 GNUNET_PSYCSTORE_message_get (store, &chn->pub_key, NULL,
2209 GNUNET_ntohll (req->start_message_id),
2210 GNUNET_ntohll (req->end_message_id),
2211 &store_recv_fragment_history,
2212 &store_recv_fragment_history_result, opcls);
2213 else
2214 GNUNET_PSYCSTORE_message_get_latest (store, &chn->pub_key, NULL,
2215 GNUNET_ntohll (req->message_limit),
2216 &store_recv_fragment_history,
2217 &store_recv_fragment_history_result,
2218 opcls);
2219
2220 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2221}
2222
2223
2224/**
2225 * Received state var from PSYCstore, send it to client.
2226 */
2227static int
2228store_recv_state_var (void *cls, const char *name,
2229 const void *value, size_t value_size)
2230{
2231 struct OperationClosure *opcls = cls;
2232 struct OperationResult *op;
2233
2234 if (NULL != name)
2235 {
2236 uint16_t name_size = strnlen (name, GNUNET_PSYC_MODIFIER_MAX_PAYLOAD) + 1;
2237 struct GNUNET_PSYC_MessageModifier *mod;
2238 op = GNUNET_malloc (sizeof (*op) + sizeof (*mod) + name_size + value_size);
2239 op->header.size = htons (sizeof (*op) + sizeof (*mod) + name_size + value_size);
2240 op->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT);
2241 op->op_id = opcls->op_id;
2242
2243 mod = (struct GNUNET_PSYC_MessageModifier *) &op[1];
2244 mod->header.size = htons (sizeof (*mod) + name_size + value_size);
2245 mod->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER);
2246 mod->name_size = htons (name_size);
2247 mod->value_size = htonl (value_size);
2248 mod->oper = htons (GNUNET_ENV_OP_ASSIGN);
2249 memcpy (&mod[1], name, name_size);
2250 memcpy (((char *) &mod[1]) + name_size, value, value_size);
2251 }
2252 else
2253 {
2254 struct GNUNET_MessageHeader *mod;
2255 op = GNUNET_malloc (sizeof (*op) + sizeof (*mod) + value_size);
2256 op->header.size = htons (sizeof (*op) + sizeof (*mod) + value_size);
2257 op->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT);
2258 op->op_id = opcls->op_id;
2259
2260 mod = (struct GNUNET_MessageHeader *) &op[1];
2261 mod->size = htons (sizeof (*mod) + value_size);
2262 mod->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT);
2263 memcpy (&mod[1], value, value_size);
2264 }
2265
2266 GNUNET_SERVER_notification_context_add (nc, opcls->client);
2267 GNUNET_SERVER_notification_context_unicast (nc, opcls->client, &op->header,
2268 GNUNET_NO);
2269 return GNUNET_YES;
2270}
2271
2272
2273/**
2274 * Received result of GNUNET_PSYCSTORE_state_get()
2275 * or GNUNET_PSYCSTORE_state_get_prefix()
2276 */
2277static void
2278store_recv_state_result (void *cls, int64_t result, const char *err_msg)
2100{ 2279{
2280 struct OperationClosure *opcls = cls;
2281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2282 "%p History replay #%" PRIu64 ": "
2283 "PSYCSTORE returned %" PRId64 " (%s)\n",
2284 opcls->chn, opcls->op_id, result, err_msg);
2101 2285
2286 client_send_result (opcls->client, opcls->op_id, result, err_msg);
2102} 2287}
2103 2288
2104 2289
@@ -2109,7 +2294,30 @@ static void
2109client_recv_state_get (void *cls, struct GNUNET_SERVER_Client *client, 2294client_recv_state_get (void *cls, struct GNUNET_SERVER_Client *client,
2110 const struct GNUNET_MessageHeader *msg) 2295 const struct GNUNET_MessageHeader *msg)
2111{ 2296{
2297 struct Channel *
2298 chn = GNUNET_SERVER_client_get_user_context (client, struct Channel);
2299 GNUNET_assert (NULL != chn);
2300
2301 const struct StateRequest *
2302 req = (const struct StateRequest *) msg;
2112 2303
2304 uint16_t name_size = ntohs (req->header.size) - sizeof (*req);
2305 const char *name = (const char *) &req[1];
2306 if (0 == name_size || '\0' != name[name_size - 1])
2307 {
2308 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2309 return;
2310 }
2311
2312 struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
2313 opcls->client = client;
2314 opcls->chn = chn;
2315 opcls->op_id = req->op_id;
2316
2317 GNUNET_PSYCSTORE_state_get (store, &chn->pub_key, name,
2318 &store_recv_state_var,
2319 &store_recv_state_result, opcls);
2320 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2113} 2321}
2114 2322
2115 2323
@@ -2120,6 +2328,30 @@ static void
2120client_recv_state_get_prefix (void *cls, struct GNUNET_SERVER_Client *client, 2328client_recv_state_get_prefix (void *cls, struct GNUNET_SERVER_Client *client,
2121 const struct GNUNET_MessageHeader *msg) 2329 const struct GNUNET_MessageHeader *msg)
2122{ 2330{
2331 struct Channel *
2332 chn = GNUNET_SERVER_client_get_user_context (client, struct Channel);
2333 GNUNET_assert (NULL != chn);
2334
2335 const struct StateRequest *
2336 req = (const struct StateRequest *) msg;
2337
2338 uint16_t name_size = ntohs (req->header.size) - sizeof (*req);
2339 const char *name = (const char *) &req[1];
2340 if (0 == name_size || '\0' != name[name_size - 1])
2341 {
2342 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2343 return;
2344 }
2345
2346 struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls));
2347 opcls->client = client;
2348 opcls->chn = chn;
2349 opcls->op_id = req->op_id;
2350
2351 GNUNET_PSYCSTORE_state_get_prefix (store, &chn->pub_key, name,
2352 &store_recv_state_var,
2353 &store_recv_state_result, opcls);
2354 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2123 2355
2124} 2356}
2125 2357
@@ -2140,8 +2372,8 @@ static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
2140 { &client_recv_membership_store, NULL, 2372 { &client_recv_membership_store, NULL,
2141 GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_MEMBERSHIP_STORE, 0 }, 2373 GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_MEMBERSHIP_STORE, 0 },
2142 2374
2143 { &client_recv_story_request, NULL, 2375 { &client_recv_history_replay, NULL,
2144 GNUNET_MESSAGE_TYPE_PSYC_STORY_REQUEST, 0 }, 2376 GNUNET_MESSAGE_TYPE_PSYC_HISTORY_REPLAY, 0 },
2145 2377
2146 { &client_recv_state_get, NULL, 2378 { &client_recv_state_get, NULL,
2147 GNUNET_MESSAGE_TYPE_PSYC_STATE_GET, 0 }, 2379 GNUNET_MESSAGE_TYPE_PSYC_STATE_GET, 0 },
diff --git a/src/psyc/psyc.h b/src/psyc/psyc.h
index 21131e7d3..f6d40ddb4 100644
--- a/src/psyc/psyc.h
+++ b/src/psyc/psyc.h
@@ -112,30 +112,39 @@ struct ChannelMembershipStoreRequest
112 */ 112 */
113 struct GNUNET_MessageHeader header; 113 struct GNUNET_MessageHeader header;
114 114
115 uint32_t reserved; 115 uint32_t reserved GNUNET_PACKED;
116
117 uint64_t op_id GNUNET_PACKED;
116 118
117 struct GNUNET_CRYPTO_EcdsaPublicKey slave_key; 119 struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
118 120
119 uint64_t announced_at; 121 uint64_t announced_at GNUNET_PACKED;
120 122
121 uint64_t effective_since; 123 uint64_t effective_since GNUNET_PACKED;
122 124
123 uint8_t did_join; 125 uint8_t did_join;
124}; 126};
125 127
126 128
127struct StoryRequest 129struct HistoryRequest
128{ 130{
129 /** 131 /**
130 * Type: GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STORY_REQUEST 132 * Type: GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_HISTORY_REQUEST
131 */ 133 */
132 struct GNUNET_MessageHeader header; 134 struct GNUNET_MessageHeader header;
133 135
134 uint64_t op_id; 136 uint32_t reserved GNUNET_PACKED;
137
138 /**
139 * ID for this operation.
140 */
141 uint64_t op_id GNUNET_PACKED;
142
143 uint64_t start_message_id GNUNET_PACKED;
135 144
136 uint64_t start_message_id; 145 uint64_t end_message_id GNUNET_PACKED;
137 146
138 uint64_t end_message_id; 147 uint64_t message_limit GNUNET_PACKED;
139}; 148};
140 149
141 150
@@ -148,10 +157,12 @@ struct StateRequest
148 */ 157 */
149 struct GNUNET_MessageHeader header; 158 struct GNUNET_MessageHeader header;
150 159
160 uint32_t reserved GNUNET_PACKED;
161
151 /** 162 /**
152 * ID for this operation. 163 * ID for this operation.
153 */ 164 */
154 uint64_t op_id; 165 uint64_t op_id GNUNET_PACKED;
155 166
156 /* Followed by NUL-terminated name. */ 167 /* Followed by NUL-terminated name. */
157}; 168};
@@ -160,25 +171,6 @@ struct StateRequest
160/**** service -> library ****/ 171/**** service -> library ****/
161 172
162 173
163struct CountersResult
164{
165 /**
166 * Type: GNUNET_MESSAGE_TYPE_PSYC_RESULT_COUNTERS
167 */
168 struct GNUNET_MessageHeader header;
169
170 /**
171 * Status code for the operation.
172 */
173 int32_t result_code GNUNET_PACKED;
174
175 /**
176 * Last message ID sent to the channel.
177 */
178 uint64_t max_message_id;
179};
180
181
182/** 174/**
183 * Answer from service to client about last operation. 175 * Answer from service to client about last operation.
184 */ 176 */
@@ -192,23 +184,22 @@ struct OperationResult
192 */ 184 */
193 struct GNUNET_MessageHeader header; 185 struct GNUNET_MessageHeader header;
194 186
187 uint32_t reserved GNUNET_PACKED;
188
195 /** 189 /**
196 * Operation ID. 190 * Operation ID.
197 */ 191 */
198 uint32_t op_id GNUNET_PACKED; 192 uint64_t op_id GNUNET_PACKED;
199 193
200 /** 194 /**
201 * Status code for the operation. 195 * Status code for the operation.
202 */ 196 */
203 int64_t result_code GNUNET_PACKED; 197 uint64_t result_code GNUNET_PACKED;
204 198
205 /* Followed by: 199 /* Followed by:
206 * - on error: NUL-terminated error message 200 * - on error: NUL-terminated error message
207 * - on success: one of the following message types 201 * - on success: one of the following message types
208 * 202 *
209 * For a STORY_RESULT:
210 * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE
211 *
212 * For a STATE_RESULT, one of: 203 * For a STATE_RESULT, one of:
213 * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER 204 * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER
214 * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT 205 * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT
diff --git a/src/psyc/psyc_api.c b/src/psyc/psyc_api.c
index ca25b1b01..8cce89704 100644
--- a/src/psyc/psyc_api.c
+++ b/src/psyc/psyc_api.c
@@ -43,6 +43,33 @@
43#define LOG(kind,...) GNUNET_log_from (kind, "psyc-api",__VA_ARGS__) 43#define LOG(kind,...) GNUNET_log_from (kind, "psyc-api",__VA_ARGS__)
44 44
45 45
46struct OperationListItem
47{
48 struct OperationListItem *prev;
49 struct OperationListItem *next;
50
51 /**
52 * Operation ID.
53 */
54 uint64_t op_id;
55
56 /**
57 * Continuation to invoke with the result of an operation.
58 */
59 GNUNET_PSYC_ResultCallback result_cb;
60
61 /**
62 * State variable result callback.
63 */
64 GNUNET_PSYC_StateVarCallback state_var_cb;
65
66 /**
67 * Closure for the callbacks.
68 */
69 void *cls;
70};
71
72
46/** 73/**
47 * Handle to access PSYC channel operations for both the master and slaves. 74 * Handle to access PSYC channel operations for both the master and slaves.
48 */ 75 */
@@ -84,6 +111,21 @@ struct GNUNET_PSYC_Channel
84 void *disconnect_cls; 111 void *disconnect_cls;
85 112
86 /** 113 /**
114 * First operation in the linked list.
115 */
116 struct OperationListItem *op_head;
117
118 /**
119 * Last operation in the linked list.
120 */
121 struct OperationListItem *op_tail;
122
123 /**
124 * Last operation ID used.
125 */
126 uint64_t last_op_id;
127
128 /**
87 * Are we polling for incoming messages right now? 129 * Are we polling for incoming messages right now?
88 */ 130 */
89 uint8_t in_receive; 131 uint8_t in_receive;
@@ -163,21 +205,82 @@ struct GNUNET_PSYC_SlaveTransmitHandle
163 205
164 206
165/** 207/**
166 * Handle to a story telling operation. 208 * Get a fresh operation ID to distinguish between PSYCstore requests.
209 *
210 * @param h Handle to the PSYCstore service.
211 * @return next operation id to use
167 */ 212 */
168struct GNUNET_PSYC_Story 213static uint64_t
214op_get_next_id (struct GNUNET_PSYC_Channel *chn)
169{ 215{
170 216 return ++chn->last_op_id;
171}; 217}
172 218
173 219
174/** 220/**
175 * Handle for a state query operation. 221 * Find operation by ID.
222 *
223 * @return Operation, or NULL if none found.
176 */ 224 */
177struct GNUNET_PSYC_StateQuery 225static struct OperationListItem *
226op_find_by_id (struct GNUNET_PSYC_Channel *chn, uint64_t op_id)
178{ 227{
228 struct OperationListItem *op = chn->op_head;
229 while (NULL != op)
230 {
231 if (op->op_id == op_id)
232 return op;
233 op = op->next;
234 }
235 return NULL;
236}
179 237
180}; 238
239static uint64_t
240op_add (struct GNUNET_PSYC_Channel *chn, GNUNET_PSYC_ResultCallback result_cb,
241 void *cls)
242{
243 if (NULL == result_cb)
244 return 0;
245
246 struct OperationListItem *op = GNUNET_malloc (sizeof (*op));
247 op->op_id = op_get_next_id (chn);
248 op->result_cb = result_cb;
249 op->cls = cls;
250 GNUNET_CONTAINER_DLL_insert_tail (chn->op_head, chn->op_tail, op);
251
252 LOG (GNUNET_ERROR_TYPE_DEBUG,
253 "%p Added operation #%" PRIu64 "\n", chn, op->op_id);
254 return op->op_id;
255}
256
257
258static int
259op_result (struct GNUNET_PSYC_Channel *chn, uint64_t op_id,
260 int64_t result_code, const char *err_msg)
261{
262 LOG (GNUNET_ERROR_TYPE_DEBUG,
263 "%p Received result for operation #%" PRIu64 ": %" PRId64 " (%s)\n",
264 chn, op_id, result_code, err_msg);
265 if (0 == op_id)
266 return GNUNET_NO;
267
268 struct OperationListItem *op = op_find_by_id (chn, op_id);
269 if (NULL == op)
270 {
271 LOG (GNUNET_ERROR_TYPE_WARNING,
272 "Could not find operation #%" PRIu64 "\n", op_id);
273 return GNUNET_NO;
274 }
275
276 GNUNET_CONTAINER_DLL_remove (chn->op_head, chn->op_tail, op);
277
278 if (NULL != op->result_cb)
279 op->result_cb (op->cls, result_code, err_msg);
280
281 GNUNET_free (op);
282 return GNUNET_YES;
283}
181 284
182 285
183static void 286static void
@@ -203,6 +306,79 @@ channel_recv_disconnect (void *cls,
203 306
204 307
205static void 308static void
309channel_recv_result (void *cls,
310 struct GNUNET_CLIENT_MANAGER_Connection *client,
311 const struct GNUNET_MessageHeader *msg)
312{
313 struct GNUNET_PSYC_Channel *
314 chn = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*chn));
315
316 uint16_t size = ntohs (msg->size);
317 const struct OperationResult *res = (const struct OperationResult *) msg;
318 const char *err_msg = NULL;
319
320 if (sizeof (struct OperationResult) < size)
321 {
322 err_msg = (const char *) &res[1];
323 if ('\0' != err_msg[size - sizeof (struct OperationResult) - 1])
324 {
325 GNUNET_break (0);
326 err_msg = NULL;
327 }
328 }
329
330 op_result (chn, GNUNET_ntohll (res->op_id),
331 GNUNET_ntohll (res->result_code) + INT64_MIN, err_msg);
332}
333
334
335static void
336channel_recv_state_result (void *cls,
337 struct GNUNET_CLIENT_MANAGER_Connection *client,
338 const struct GNUNET_MessageHeader *msg)
339{
340 struct GNUNET_PSYC_Channel *
341 chn = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*chn));
342
343 const struct OperationResult *res = (const struct OperationResult *) msg;
344 struct OperationListItem *op = op_find_by_id (chn, GNUNET_ntohll (res->op_id));
345 if (NULL == op || NULL == op->state_var_cb)
346 return;
347
348 const struct GNUNET_MessageHeader *modc = (struct GNUNET_MessageHeader *) &op[1];
349 uint16_t modc_size = ntohs (modc->size);
350 if (ntohs (msg->size) - sizeof (*msg) != modc_size)
351 {
352 GNUNET_break (0);
353 return;
354 }
355 switch (ntohs (modc->type))
356 {
357 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
358 {
359 const struct GNUNET_PSYC_MessageModifier *
360 mod = (const struct GNUNET_PSYC_MessageModifier *) modc;
361
362 const char *name = (const char *) &mod[1];
363 uint16_t name_size = ntohs (mod->name_size);
364 if ('\0' != name[name_size - 1])
365 {
366 GNUNET_break (0);
367 return;
368 }
369 op->state_var_cb (op->cls, name, name + name_size, ntohs (mod->value_size));
370 break;
371 }
372
373 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
374 op->state_var_cb (op->cls, NULL, (const char *) &modc[1],
375 modc_size - sizeof (*modc));
376 break;
377 }
378}
379
380
381static void
206channel_recv_message (void *cls, 382channel_recv_message (void *cls,
207 struct GNUNET_CLIENT_MANAGER_Connection *client, 383 struct GNUNET_CLIENT_MANAGER_Connection *client,
208 const struct GNUNET_MessageHeader *msg) 384 const struct GNUNET_MessageHeader *msg)
@@ -234,9 +410,16 @@ master_recv_start_ack (void *cls,
234 mst = GNUNET_CLIENT_MANAGER_get_user_context_ (client, 410 mst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
235 sizeof (struct GNUNET_PSYC_Channel)); 411 sizeof (struct GNUNET_PSYC_Channel));
236 412
237 struct CountersResult *cres = (struct CountersResult *) msg; 413 struct GNUNET_PSYC_CountersResultMessage *
414 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
415 int32_t result = ntohl (cres->result_code) + INT32_MIN;
416 if (GNUNET_OK != result && GNUNET_NO != result)
417 {
418 LOG (GNUNET_ERROR_TYPE_ERROR, "Could not start master.\n");
419 GNUNET_break (0);
420 }
238 if (NULL != mst->start_cb) 421 if (NULL != mst->start_cb)
239 mst->start_cb (mst->cb_cls, GNUNET_ntohll (cres->max_message_id)); 422 mst->start_cb (mst->cb_cls, result, GNUNET_ntohll (cres->max_message_id));
240} 423}
241 424
242 425
@@ -279,9 +462,16 @@ slave_recv_join_ack (void *cls,
279 struct GNUNET_PSYC_Slave * 462 struct GNUNET_PSYC_Slave *
280 slv = GNUNET_CLIENT_MANAGER_get_user_context_ (client, 463 slv = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
281 sizeof (struct GNUNET_PSYC_Channel)); 464 sizeof (struct GNUNET_PSYC_Channel));
282 struct CountersResult *cres = (struct CountersResult *) msg; 465 struct GNUNET_PSYC_CountersResultMessage *
466 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
467 int32_t result = ntohl (cres->result_code) + INT32_MIN;
468 if (GNUNET_YES != result && GNUNET_NO != result)
469 {
470 LOG (GNUNET_ERROR_TYPE_ERROR, "Could not join slave.\n");
471 GNUNET_break (0);
472 }
283 if (NULL != slv->connect_cb) 473 if (NULL != slv->connect_cb)
284 slv->connect_cb (slv->cb_cls, GNUNET_ntohll (cres->max_message_id)); 474 slv->connect_cb (slv->cb_cls, result, GNUNET_ntohll (cres->max_message_id));
285} 475}
286 476
287 477
@@ -317,12 +507,20 @@ static struct GNUNET_CLIENT_MANAGER_MessageHandler master_handlers[] =
317 507
318 { &master_recv_start_ack, NULL, 508 { &master_recv_start_ack, NULL,
319 GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK, 509 GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK,
320 sizeof (struct CountersResult), GNUNET_NO }, 510 sizeof (struct GNUNET_PSYC_CountersResultMessage), GNUNET_NO },
321 511
322 { &master_recv_join_request, NULL, 512 { &master_recv_join_request, NULL,
323 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST, 513 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
324 sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES }, 514 sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
325 515
516 { &channel_recv_state_result, NULL,
517 GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT,
518 sizeof (struct OperationResult), GNUNET_YES },
519
520 { &channel_recv_result, NULL,
521 GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE,
522 sizeof (struct OperationResult), GNUNET_YES },
523
326 { &channel_recv_disconnect, NULL, 0, 0, GNUNET_NO }, 524 { &channel_recv_disconnect, NULL, 0, 0, GNUNET_NO },
327 525
328 { NULL, NULL, 0, 0, GNUNET_NO } 526 { NULL, NULL, 0, 0, GNUNET_NO }
@@ -341,12 +539,20 @@ static struct GNUNET_CLIENT_MANAGER_MessageHandler slave_handlers[] =
341 539
342 { &slave_recv_join_ack, NULL, 540 { &slave_recv_join_ack, NULL,
343 GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK, 541 GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK,
344 sizeof (struct CountersResult), GNUNET_NO }, 542 sizeof (struct GNUNET_PSYC_CountersResultMessage), GNUNET_NO },
345 543
346 { &slave_recv_join_decision, NULL, 544 { &slave_recv_join_decision, NULL,
347 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 545 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
348 sizeof (struct GNUNET_PSYC_JoinDecisionMessage), GNUNET_YES }, 546 sizeof (struct GNUNET_PSYC_JoinDecisionMessage), GNUNET_YES },
349 547
548 { &channel_recv_state_result, NULL,
549 GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT,
550 sizeof (struct OperationResult), GNUNET_YES },
551
552 { &channel_recv_result, NULL,
553 GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE,
554 sizeof (struct OperationResult), GNUNET_YES },
555
350 { &channel_recv_disconnect, NULL, 0, 0, GNUNET_NO }, 556 { &channel_recv_disconnect, NULL, 0, 0, GNUNET_NO },
351 557
352 { NULL, NULL, 0, 0, GNUNET_NO } 558 { NULL, NULL, 0, 0, GNUNET_NO }
@@ -808,7 +1014,9 @@ void
808GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *chn, 1014GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *chn,
809 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, 1015 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
810 uint64_t announced_at, 1016 uint64_t announced_at,
811 uint64_t effective_since) 1017 uint64_t effective_since,
1018 GNUNET_PSYC_ResultCallback result_cb,
1019 void *cls)
812{ 1020{
813 struct ChannelMembershipStoreRequest *req = GNUNET_malloc (sizeof (*req)); 1021 struct ChannelMembershipStoreRequest *req = GNUNET_malloc (sizeof (*req));
814 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_MEMBERSHIP_STORE); 1022 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_MEMBERSHIP_STORE);
@@ -817,6 +1025,8 @@ GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *chn,
817 req->announced_at = GNUNET_htonll (announced_at); 1025 req->announced_at = GNUNET_htonll (announced_at);
818 req->effective_since = GNUNET_htonll (effective_since); 1026 req->effective_since = GNUNET_htonll (effective_since);
819 req->did_join = GNUNET_YES; 1027 req->did_join = GNUNET_YES;
1028 req->op_id = GNUNET_htonll (op_add (chn, result_cb, cls));
1029
820 GNUNET_CLIENT_MANAGER_transmit (chn->client, &req->header); 1030 GNUNET_CLIENT_MANAGER_transmit (chn->client, &req->header);
821} 1031}
822 1032
@@ -845,7 +1055,9 @@ GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *chn,
845void 1055void
846GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *chn, 1056GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *chn,
847 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, 1057 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
848 uint64_t announced_at) 1058 uint64_t announced_at,
1059 GNUNET_PSYC_ResultCallback result_cb,
1060 void *cls)
849{ 1061{
850 struct ChannelMembershipStoreRequest *req = GNUNET_malloc (sizeof (*req)); 1062 struct ChannelMembershipStoreRequest *req = GNUNET_malloc (sizeof (*req));
851 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_MEMBERSHIP_STORE); 1063 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_MEMBERSHIP_STORE);
@@ -853,57 +1065,85 @@ GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *chn,
853 req->slave_key = *slave_key; 1065 req->slave_key = *slave_key;
854 req->announced_at = GNUNET_htonll (announced_at); 1066 req->announced_at = GNUNET_htonll (announced_at);
855 req->did_join = GNUNET_NO; 1067 req->did_join = GNUNET_NO;
1068 req->op_id = GNUNET_htonll (op_add (chn, result_cb, cls));
1069
856 GNUNET_CLIENT_MANAGER_transmit (chn->client, &req->header); 1070 GNUNET_CLIENT_MANAGER_transmit (chn->client, &req->header);
857} 1071}
858 1072
859 1073
860/** 1074/**
861 * Request to be told the message history of the channel. 1075 * Request to replay a part of the message history of the channel.
862 * 1076 *
863 * Historic messages (but NOT the state at the time) will be replayed (given to 1077 * Historic messages (but NOT the state at the time) will be replayed (given to
864 * the normal method handlers) if available and if access is permitted. 1078 * the normal method handlers) if available and if access is permitted.
865 * 1079 *
866 * To get the latest message, use 0 for both the start and end message ID. 1080 * @param channel
867 * 1081 * Which channel should be replayed?
868 * @param channel Which channel should be replayed? 1082 * @param start_message_id
869 * @param start_message_id Earliest interesting point in history. 1083 * Earliest interesting point in history.
870 * @param end_message_id Last (exclusive) interesting point in history. 1084 * @param end_message_id
871 * @param message_cb Function to invoke on message parts received from the story. 1085 * Last (inclusive) interesting point in history.
872 * @param finish_cb Function to call when the requested story has been fully 1086 * FIXME: @param method_prefix
873 * told (counting message IDs might not suffice, as some messages 1087 * Retrieve only messages with a matching method prefix.
874 * might be secret and thus the listener would not know the story is 1088 * @param result_cb
875 * finished without being told explicitly) once this function 1089 * Function to call when the requested history has been fully replayed.
876 * has been called, the client must not call 1090 * @param cls
877 * GNUNET_PSYC_channel_story_tell_cancel() anymore. 1091 * Closure for the callbacks.
878 * @param cls Closure for the callbacks. 1092 *
879 * 1093 * @return Handle to cancel history replay operation.
880 * @return Handle to cancel story telling operation.
881 */ 1094 */
882struct GNUNET_PSYC_Story * 1095void
883GNUNET_PSYC_channel_story_tell (struct GNUNET_PSYC_Channel *channel, 1096GNUNET_PSYC_channel_history_replay (struct GNUNET_PSYC_Channel *chn,
884 uint64_t start_message_id, 1097 uint64_t start_message_id,
885 uint64_t end_message_id, 1098 uint64_t end_message_id,
886 GNUNET_PSYC_MessageCallback message_cb, 1099 /* FIXME: const char *method_prefix, */
887 GNUNET_PSYC_MessagePartCallback message_part_cb, 1100 GNUNET_PSYC_ResultCallback result_cb,
888 GNUNET_PSYC_FinishCallback finish_cb, 1101 void *cls)
889 void *cls)
890{ 1102{
891 return NULL; 1103 struct HistoryRequest *req = GNUNET_malloc (sizeof (*req));
1104 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_HISTORY_REPLAY);
1105 req->header.size = htons (sizeof (*req));
1106 req->start_message_id = GNUNET_htonll (start_message_id);
1107 req->end_message_id = GNUNET_htonll (end_message_id);
1108 req->op_id = GNUNET_htonll (op_add (chn, result_cb, cls));
1109
1110 GNUNET_CLIENT_MANAGER_transmit (chn->client, &req->header);
892} 1111}
893 1112
894 1113
895/** 1114/**
896 * Abort story telling. 1115 * Request to replay the latest messages from the message history of the channel.
897 * 1116 *
898 * This function must not be called from within method handlers (as given to 1117 * Historic messages (but NOT the state at the time) will be replayed (given to
899 * GNUNET_PSYC_slave_join()) of the slave. 1118 * the normal method handlers) if available and if access is permitted.
900 * 1119 *
901 * @param story Story telling operation to stop. 1120 * @param channel
1121 * Which channel should be replayed?
1122 * @param message_limit
1123 * Maximum number of messages to replay.
1124 * FIXME: @param method_prefix
1125 * Retrieve only messages with a matching method prefix.
1126 * @param result_cb
1127 * Function to call when the requested history has been fully replayed.
1128 * @param cls
1129 * Closure for the callbacks.
1130 *
1131 * @return Handle to cancel history replay operation.
902 */ 1132 */
903void 1133void
904GNUNET_PSYC_channel_story_tell_cancel (struct GNUNET_PSYC_Story *story) 1134GNUNET_PSYC_channel_history_replay_latest (struct GNUNET_PSYC_Channel *chn,
1135 uint64_t message_limit,
1136 /* FIXME: const char *method_prefix, */
1137 GNUNET_PSYC_ResultCallback result_cb,
1138 void *cls)
905{ 1139{
1140 struct HistoryRequest *req = GNUNET_malloc (sizeof (*req));
1141 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_HISTORY_REPLAY);
1142 req->header.size = htons (sizeof (*req));
1143 req->message_limit = GNUNET_htonll (message_limit);
1144 req->op_id = GNUNET_htonll (op_add (chn, result_cb, cls));
906 1145
1146 GNUNET_CLIENT_MANAGER_transmit (chn->client, &req->header);
907} 1147}
908 1148
909 1149
@@ -914,22 +1154,35 @@ GNUNET_PSYC_channel_story_tell_cancel (struct GNUNET_PSYC_Story *story)
914 * less-specific name is matched; for example, requesting "_a_b" will match "_a" 1154 * less-specific name is matched; for example, requesting "_a_b" will match "_a"
915 * if "_a_b" does not exist. 1155 * if "_a_b" does not exist.
916 * 1156 *
917 * @param channel Channel handle. 1157 * @param channel
918 * @param full_name Full name of the requested variable, the actual variable 1158 * Channel handle.
919 * returned might have a shorter name.. 1159 * @param full_name
920 * @param cb Function called once when a matching state variable is found. 1160 * Full name of the requested variable.
1161 * The actual variable returned might have a shorter name.
1162 * @param var_cb
1163 * Function called once when a matching state variable is found.
921 * Not called if there's no matching state variable. 1164 * Not called if there's no matching state variable.
922 * @param cb_cls Closure for the callbacks. 1165 * @param result_cb
923 * 1166 * Function called after the operation finished.
924 * @return Handle that can be used to cancel the query operation. 1167 * (i.e. all state variables have been returned via @a state_cb)
1168 * @param cls
1169 * Closure for the callbacks.
925 */ 1170 */
926struct GNUNET_PSYC_StateQuery * 1171void
927GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel, 1172GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *chn,
928 const char *full_name, 1173 const char *full_name,
929 GNUNET_PSYC_StateCallback cb, 1174 GNUNET_PSYC_StateVarCallback var_cb,
930 void *cb_cls) 1175 GNUNET_PSYC_ResultCallback result_cb,
1176 void *cls)
931{ 1177{
932 return NULL; 1178 size_t name_size = strlen (full_name) + 1;
1179 struct StateRequest *req = GNUNET_malloc (sizeof (*req) + name_size);
1180 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_STATE_GET);
1181 req->header.size = htons (sizeof (*req) + name_size);
1182 req->op_id = GNUNET_htonll (op_add (chn, result_cb, cls));
1183 memcpy (&req[1], full_name, name_size);
1184
1185 GNUNET_CLIENT_MANAGER_transmit (chn->client, &req->header);
933} 1186}
934 1187
935 1188
@@ -943,33 +1196,34 @@ GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel,
943 * The @a state_cb is invoked on all matching state variables asynchronously, as 1196 * The @a state_cb is invoked on all matching state variables asynchronously, as
944 * the state is stored in and retrieved from the PSYCstore, 1197 * the state is stored in and retrieved from the PSYCstore,
945 * 1198 *
946 * @param channel Channel handle. 1199 * @param channel
947 * @param name_prefix Prefix of the state variable name to match. 1200 * Channel handle.
948 * @param cb Function to call with the matching state variables. 1201 * @param name_prefix
949 * @param cb_cls Closure for the callbacks. 1202 * Prefix of the state variable name to match.
950 * 1203 * @param var_cb
951 * @return Handle that can be used to cancel the query operation. 1204 * Function called once when a matching state variable is found.
952 */ 1205 * Not called if there's no matching state variable.
953struct GNUNET_PSYC_StateQuery * 1206 * @param result_cb
954GNUNET_PSYC_channel_state_get_prefix (struct GNUNET_PSYC_Channel *channel, 1207 * Function called after the operation finished.
955 const char *name_prefix, 1208 * (i.e. all state variables have been returned via @a state_cb)
956 GNUNET_PSYC_StateCallback cb, 1209 * @param cls
957 void *cb_cls) 1210 * Closure for the callbacks.
958{
959 return NULL;
960}
961
962
963/**
964 * Cancel a state query operation.
965 *
966 * @param query Handle for the operation to cancel.
967 */ 1211 */
968void 1212void
969GNUNET_PSYC_channel_state_get_cancel (struct GNUNET_PSYC_StateQuery *query) 1213GNUNET_PSYC_channel_state_get_prefix (struct GNUNET_PSYC_Channel *chn,
1214 const char *name_prefix,
1215 GNUNET_PSYC_StateVarCallback var_cb,
1216 GNUNET_PSYC_ResultCallback result_cb,
1217 void *cls)
970{ 1218{
1219 size_t name_size = strlen (name_prefix) + 1;
1220 struct StateRequest *req = GNUNET_malloc (sizeof (*req) + name_size);
1221 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_STATE_GET);
1222 req->header.size = htons (sizeof (*req) + name_size);
1223 req->op_id = GNUNET_htonll (op_add (chn, result_cb, cls));
1224 memcpy (&req[1], name_prefix, name_size);
971 1225
1226 GNUNET_CLIENT_MANAGER_transmit (chn->client, &req->header);
972} 1227}
973 1228
974
975/* end of psyc_api.c */ 1229/* end of psyc_api.c */
diff --git a/src/psyc/test_psyc.c b/src/psyc/test_psyc.c
index 5eadef62c..044895809 100644
--- a/src/psyc/test_psyc.c
+++ b/src/psyc/test_psyc.c
@@ -35,6 +35,7 @@
35#include "gnunet_env_lib.h" 35#include "gnunet_env_lib.h"
36#include "gnunet_psyc_util_lib.h" 36#include "gnunet_psyc_util_lib.h"
37#include "gnunet_psyc_service.h" 37#include "gnunet_psyc_service.h"
38#include "gnunet_core_service.h"
38 39
39#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) 40#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
40 41
@@ -45,6 +46,9 @@ int res;
45 46
46const struct GNUNET_CONFIGURATION_Handle *cfg; 47const struct GNUNET_CONFIGURATION_Handle *cfg;
47 48
49struct GNUNET_CORE_Handle *core;
50struct GNUNET_PeerIdentity this_peer;
51
48/** 52/**
49 * Handle for task for timeout termination. 53 * Handle for task for timeout termination.
50 */ 54 */
@@ -53,6 +57,8 @@ GNUNET_SCHEDULER_TaskIdentifier end_badly_task;
53struct GNUNET_PSYC_Master *mst; 57struct GNUNET_PSYC_Master *mst;
54struct GNUNET_PSYC_Slave *slv; 58struct GNUNET_PSYC_Slave *slv;
55 59
60struct GNUNET_PSYC_Channel *mst_chn, *slv_chn;
61
56struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key; 62struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
57struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key; 63struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key;
58 64
@@ -80,9 +86,19 @@ uint8_t join_req_count;
80 86
81enum 87enum
82{ 88{
83 TEST_NONE, 89 TEST_NONE = 0,
84 TEST_SLAVE_TRANSMIT, 90 TEST_MASTER_START = 1,
85 TEST_MASTER_TRANSMIT, 91 TEST_SLAVE_JOIN = 2,
92 TEST_SLAVE_TRANSMIT = 3,
93 TEST_MASTER_TRANSMIT = 4,
94 TEST_MASTER_HISTORY_REPLAY_LATEST = 5,
95 TEST_SLAVE_HISTORY_REPLAY_LATEST = 6,
96 TEST_MASTER_HISTORY_REPLAY = 7,
97 TEST_SLAVE_HISTORY_REPLAY = 8,
98 TEST_MASTER_STATE_GET = 9,
99 TEST_SLAVE_STATE_GET = 10,
100 TEST_MASTER_STATE_GET_PREFIX = 11,
101 TEST_SLAVE_STATE_GET_PREFIX = 12,
86} test; 102} test;
87 103
88 104
@@ -118,6 +134,11 @@ void slave_parted (void *cls)
118void 134void
119cleanup () 135cleanup ()
120{ 136{
137 if (NULL != core)
138 {
139 GNUNET_CORE_disconnect (core);
140 core = NULL;
141 }
121 if (NULL != slv) 142 if (NULL != slv)
122 { 143 {
123 GNUNET_PSYC_slave_part (slv, GNUNET_NO, &slave_parted, NULL); 144 GNUNET_PSYC_slave_part (slv, GNUNET_NO, &slave_parted, NULL);
@@ -177,13 +198,203 @@ end ()
177 198
178 199
179void 200void
201state_get_var (void *cls, const char *name, const void *value, size_t value_size)
202{
203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
204 "Got state var: %s\n%.*s\n", name, value_size, value);
205}
206
207
208/*** Slave state_get_prefix() ***/
209
210void
211slave_state_get_prefix_result (void *cls, int64_t result, const char *err_msg)
212{
213 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
214 "slave_state_get_prefix:\t%" PRId64 " (%s)\n", result, err_msg);
215 // FIXME: GNUNET_assert (2 == result);
216 end ();
217}
218
219
220void
221slave_state_get_prefix ()
222{
223 test = TEST_SLAVE_STATE_GET_PREFIX;
224 GNUNET_PSYC_channel_state_get_prefix (slv_chn, "_foo", &state_get_var,
225 &slave_state_get_prefix_result, NULL);
226}
227
228
229/*** Master state_get_prefix() ***/
230
231
232void
233master_state_get_prefix_result (void *cls, int64_t result, const char *err_msg)
234{
235 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
236 "master_state_get_prefix:\t%" PRId64 " (%s)\n", result, err_msg);
237 // FIXME: GNUNET_assert (2 == result);
238 slave_state_get_prefix ();
239}
240
241
242void
243master_state_get_prefix ()
244{
245 test = TEST_MASTER_STATE_GET_PREFIX;
246 GNUNET_PSYC_channel_state_get_prefix (mst_chn, "_foo", &state_get_var,
247 &master_state_get_prefix_result, NULL);
248}
249
250
251/*** Slave state_get() ***/
252
253
254void
255slave_state_get_result (void *cls, int64_t result, const char *err_msg)
256{
257 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
258 "slave_state_get:\t%" PRId64 " (%s)\n", result, err_msg);
259 // FIXME: GNUNET_assert (2 == result);
260 master_state_get_prefix ();
261}
262
263
264void
265slave_state_get ()
266{
267 test = TEST_SLAVE_STATE_GET;
268 GNUNET_PSYC_channel_state_get (slv_chn, "_foo_bar_baz", &state_get_var,
269 &slave_state_get_result, NULL);
270}
271
272
273/*** Master state_get() ***/
274
275
276void
277master_state_get_result (void *cls, int64_t result, const char *err_msg)
278{
279 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
280 "master_state_get:\t%" PRId64 " (%s)\n", result, err_msg);
281 // FIXME: GNUNET_assert (1 == result);
282 slave_state_get ();
283}
284
285
286void
287master_state_get ()
288{
289 test = TEST_MASTER_STATE_GET;
290 GNUNET_PSYC_channel_state_get (mst_chn, "_foo_bar_baz", &state_get_var,
291 &master_state_get_result, NULL);
292}
293
294
295/*** Slave history_replay() ***/
296
297void
298slave_history_replay_result (void *cls, int64_t result, const char *err_msg)
299{
300 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
301 "slave_history_replay:\t%" PRId64 " (%s)\n", result, err_msg);
302 GNUNET_assert (9 == result);
303
304 master_state_get ();
305}
306
307
308void
309slave_history_replay ()
310{
311 test = TEST_SLAVE_HISTORY_REPLAY;
312 GNUNET_PSYC_channel_history_replay (slv_chn, 1, 1,
313 &slave_history_replay_result,
314 NULL);
315}
316
317
318/*** Master history_replay() ***/
319
320
321void
322master_history_replay_result (void *cls, int64_t result, const char *err_msg)
323{
324 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
325 "master_history_replay:\t%" PRId64 " (%s)\n", result, err_msg);
326 GNUNET_assert (9 == result);
327
328 slave_history_replay ();
329}
330
331
332void
333master_history_replay ()
334{
335 test = TEST_MASTER_HISTORY_REPLAY;
336 GNUNET_PSYC_channel_history_replay (mst_chn, 1, 1,
337 &master_history_replay_result,
338 NULL);
339}
340
341
342/*** Slave history_replay_latest() ***/
343
344
345void
346slave_history_replay_latest_result (void *cls, int64_t result, const char *err_msg)
347{
348 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
349 "slave_history_replay_latest:\t%" PRId64 " (%s)\n", result, err_msg);
350 GNUNET_assert (9 == result);
351
352 master_history_replay ();
353}
354
355
356void
357slave_history_replay_latest ()
358{
359 test = TEST_SLAVE_HISTORY_REPLAY_LATEST;
360 GNUNET_PSYC_channel_history_replay_latest (slv_chn, 1,
361 &slave_history_replay_latest_result,
362 NULL);
363}
364
365
366/*** Master history_replay_latest() ***/
367
368
369void
370master_history_replay_latest_result (void *cls, int64_t result, const char *err_msg)
371{
372 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
373 "master_history_replay_latest:\t%" PRId64 " (%s)\n", result, err_msg);
374 GNUNET_assert (9 == result);
375
376 slave_history_replay_latest ();
377}
378
379
380void
381master_history_replay_latest ()
382{
383 test = TEST_MASTER_HISTORY_REPLAY_LATEST;
384 GNUNET_PSYC_channel_history_replay_latest (mst_chn, 1,
385 &master_history_replay_latest_result,
386 NULL);
387}
388
389
390void
180master_message_cb (void *cls, uint64_t message_id, uint32_t flags, 391master_message_cb (void *cls, uint64_t message_id, uint32_t flags,
181 const struct GNUNET_PSYC_MessageHeader *msg) 392 const struct GNUNET_PSYC_MessageHeader *msg)
182{ 393{
183 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 394 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
184 "Master got PSYC message fragment of size %u " 395 "Test #%d: Master got PSYC message fragment of size %u "
185 "belonging to message ID %llu with flags %x\n", 396 "belonging to message ID %" PRIu64 " with flags %x\n",
186 ntohs (msg->header.size), message_id, flags); 397 test, ntohs (msg->header.size), message_id, flags);
187 // FIXME 398 // FIXME
188} 399}
189 400
@@ -196,7 +407,7 @@ master_message_part_cb (void *cls, uint64_t message_id,
196 if (NULL == msg) 407 if (NULL == msg)
197 { 408 {
198 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 409 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
199 "Error while receiving message %llu\n", message_id); 410 "Error while receiving message %" PRIu64 "\n", message_id);
200 return; 411 return;
201 } 412 }
202 413
@@ -204,9 +415,9 @@ master_message_part_cb (void *cls, uint64_t message_id,
204 uint16_t size = ntohs (msg->size); 415 uint16_t size = ntohs (msg->size);
205 416
206 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 417 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
207 "Master got message part of type %u and size %u " 418 "Test #%d: Master got message part of type %u and size %u "
208 "belonging to message ID %llu with flags %x\n", 419 "belonging to message ID %" PRIu64 " with flags %x\n",
209 type, size, message_id, flags); 420 test, type, size, message_id, flags);
210 421
211 switch (test) 422 switch (test)
212 { 423 {
@@ -227,6 +438,18 @@ master_message_part_cb (void *cls, uint64_t message_id,
227 case TEST_MASTER_TRANSMIT: 438 case TEST_MASTER_TRANSMIT:
228 break; 439 break;
229 440
441 case TEST_MASTER_HISTORY_REPLAY:
442 case TEST_MASTER_HISTORY_REPLAY_LATEST:
443 if (GNUNET_PSYC_MESSAGE_HISTORIC != flags)
444 {
445 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
446 "Test #%d: Unexpected flags for historic message: %x" PRIu32 "\n",
447 flags);
448 GNUNET_assert (0);
449 return;
450 }
451 break;
452
230 default: 453 default:
231 GNUNET_assert (0); 454 GNUNET_assert (0);
232 } 455 }
@@ -238,9 +461,9 @@ slave_message_cb (void *cls, uint64_t message_id, uint32_t flags,
238 const struct GNUNET_PSYC_MessageHeader *msg) 461 const struct GNUNET_PSYC_MessageHeader *msg)
239{ 462{
240 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 463 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
241 "Slave got PSYC message fragment of size %u " 464 "Test #%d: Slave got PSYC message fragment of size %u "
242 "belonging to message ID %llu with flags %x\n", 465 "belonging to message ID %" PRIu64 " with flags %x\n",
243 ntohs (msg->header.size), message_id, flags); 466 test, ntohs (msg->header.size), message_id, flags);
244 // FIXME 467 // FIXME
245} 468}
246 469
@@ -253,7 +476,7 @@ slave_message_part_cb (void *cls, uint64_t message_id,
253 if (NULL == msg) 476 if (NULL == msg)
254 { 477 {
255 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 478 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
256 "Error while receiving message %llu\n", message_id); 479 "Error while receiving message " PRIu64 "\n", message_id);
257 return; 480 return;
258 } 481 }
259 482
@@ -261,15 +484,27 @@ slave_message_part_cb (void *cls, uint64_t message_id,
261 uint16_t size = ntohs (msg->size); 484 uint16_t size = ntohs (msg->size);
262 485
263 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 486 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
264 "Slave got message part of type %u and size %u " 487 "Test #%d: Slave got message part of type %u and size %u "
265 "belonging to message ID %llu with flags %x\n", 488 "belonging to message ID %" PRIu64 " with flags %x\n",
266 type, size, message_id, flags); 489 test, type, size, message_id, flags);
267 490
268 switch (test) 491 switch (test)
269 { 492 {
270 case TEST_MASTER_TRANSMIT: 493 case TEST_MASTER_TRANSMIT:
271 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END == type) 494 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END == type)
272 end (); 495 master_history_replay_latest ();
496 break;
497
498 case TEST_SLAVE_HISTORY_REPLAY:
499 case TEST_SLAVE_HISTORY_REPLAY_LATEST:
500 if (GNUNET_PSYC_MESSAGE_HISTORIC != flags)
501 {
502 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
503 "Test #%d: Unexpected flags for historic message: %x" PRIu32 "\n",
504 flags);
505 GNUNET_assert (0);
506 return;
507 }
273 break; 508 break;
274 509
275 default: 510 default:
@@ -417,7 +652,6 @@ slave_transmit ()
417{ 652{
418 653
419 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Slave sending request to master.\n"); 654 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Slave sending request to master.\n");
420
421 test = TEST_SLAVE_TRANSMIT; 655 test = TEST_SLAVE_TRANSMIT;
422 656
423 tmit = GNUNET_new (struct TransmitClosure); 657 tmit = GNUNET_new (struct TransmitClosure);
@@ -438,6 +672,29 @@ slave_transmit ()
438 672
439 673
440void 674void
675slave_remove_cb (void *cls, int64_t result, const char *err_msg)
676{
677 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
678 "slave_remove:\t%" PRId64 " (%s)\n", result, err_msg);
679
680 slave_transmit ();
681}
682
683
684void
685slave_add_cb (void *cls, int64_t result, const char *err_msg)
686{
687 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
688 "slave_add:\t%" PRId64 " (%s)\n", result, err_msg);
689
690 struct GNUNET_PSYC_Channel *chn = cls;
691 GNUNET_PSYC_channel_slave_remove (chn, &slave_pub_key, 2,
692 &slave_remove_cb, chn);
693
694}
695
696
697void
441join_decision_cb (void *cls, 698join_decision_cb (void *cls,
442 const struct GNUNET_PSYC_JoinDecisionMessage *dcsn, 699 const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
443 int is_admitted, 700 int is_admitted,
@@ -453,7 +710,8 @@ join_decision_cb (void *cls,
453 return; 710 return;
454 } 711 }
455 712
456 slave_transmit (); 713 struct GNUNET_PSYC_Channel *chn = GNUNET_PSYC_master_get_channel (mst);
714 GNUNET_PSYC_channel_slave_add (chn, &slave_pub_key, 2, 2, &slave_add_cb, chn);
457} 715}
458 716
459 717
@@ -473,19 +731,17 @@ join_request_cb (void *cls,
473 /* Reject first request */ 731 /* Reject first request */
474 int is_admitted = (0 < join_req_count++) ? GNUNET_YES : GNUNET_NO; 732 int is_admitted = (0 < join_req_count++) ? GNUNET_YES : GNUNET_NO;
475 GNUNET_PSYC_join_decision (jh, is_admitted, 0, NULL, NULL); 733 GNUNET_PSYC_join_decision (jh, is_admitted, 0, NULL, NULL);
476
477 /* Membership store */
478 struct GNUNET_PSYC_Channel *chn = GNUNET_PSYC_master_get_channel (mst);
479 GNUNET_PSYC_channel_slave_add (chn, slave_key, 2, 2);
480 GNUNET_PSYC_channel_slave_remove (chn, &slave_pub_key, 2);
481} 734}
482 735
483 736
484void 737void
485slave_connect_cb (void *cls, uint64_t max_message_id) 738slave_connect_cb (void *cls, int result, uint64_t max_message_id)
486{ 739{
487 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 740 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
488 "Slave connected: %lu\n", max_message_id); 741 "Slave connected: %d, max_message_id: %" PRIu64 "\n",
742 result, max_message_id);
743 GNUNET_assert (TEST_SLAVE_JOIN == test);
744 GNUNET_assert (GNUNET_OK == result || GNUNET_NO == result);
489} 745}
490 746
491 747
@@ -493,8 +749,9 @@ void
493slave_join () 749slave_join ()
494{ 750{
495 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Joining slave.\n"); 751 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Joining slave.\n");
752 test = TEST_SLAVE_JOIN;
496 753
497 struct GNUNET_PeerIdentity origin = {}; // FIXME: this peer 754 struct GNUNET_PeerIdentity origin = this_peer;
498 struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); 755 struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create ();
499 GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN, 756 GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN,
500 "_foo", "bar baz", 7); 757 "_foo", "bar baz", 7);
@@ -507,6 +764,7 @@ slave_join ()
507 &slave_message_cb, &slave_message_part_cb, 764 &slave_message_cb, &slave_message_part_cb,
508 &slave_connect_cb, &join_decision_cb, NULL, 765 &slave_connect_cb, &join_decision_cb, NULL,
509 join_msg); 766 join_msg);
767 slv_chn = GNUNET_PSYC_slave_get_channel (slv);
510 GNUNET_ENV_environment_destroy (env); 768 GNUNET_ENV_environment_destroy (env);
511} 769}
512 770
@@ -564,10 +822,13 @@ master_transmit ()
564 822
565 823
566void 824void
567master_start_cb (void *cls, uint64_t max_message_id) 825master_start_cb (void *cls, int result, uint64_t max_message_id)
568{ 826{
569 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
570 "Master started: %" PRIu64 "\n", max_message_id); 828 "Master started: %d, max_message_id: %" PRIu64 "\n",
829 result, max_message_id);
830 GNUNET_assert (TEST_MASTER_START == test);
831 GNUNET_assert (GNUNET_OK == result || GNUNET_NO == result);
571 slave_join (); 832 slave_join ();
572} 833}
573 834
@@ -576,10 +837,12 @@ void
576master_start () 837master_start ()
577{ 838{
578 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting master.\n"); 839 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting master.\n");
840 test = TEST_MASTER_START;
579 mst = GNUNET_PSYC_master_start (cfg, channel_key, GNUNET_PSYC_CHANNEL_PRIVATE, 841 mst = GNUNET_PSYC_master_start (cfg, channel_key, GNUNET_PSYC_CHANNEL_PRIVATE,
580 &master_start_cb, &join_request_cb, 842 &master_start_cb, &join_request_cb,
581 &master_message_cb, &master_message_part_cb, 843 &master_message_cb, &master_message_part_cb,
582 NULL); 844 NULL);
845 mst_chn = GNUNET_PSYC_master_get_channel (mst);
583} 846}
584 847
585void 848void
@@ -589,6 +852,21 @@ schedule_master_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
589} 852}
590 853
591 854
855void
856core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity)
857{
858 this_peer = *my_identity;
859
860#if DEBUG_TEST_PSYC
861 master_start ();
862#else
863 /* Allow some time for the services to initialize. */
864 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
865 &schedule_master_start, NULL);
866#endif
867
868}
869
592/** 870/**
593 * Main function of the test, run from scheduler. 871 * Main function of the test, run from scheduler.
594 * 872 *
@@ -615,14 +893,8 @@ run (void *cls,
615 GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key); 893 GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
616 GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key); 894 GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);
617 895
618#if DEBUG_TEST_PSYC 896 core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL,
619 master_start (); 897 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
620#else
621 /* Allow some time for the services to initialize. */
622 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
623 &schedule_master_start, NULL);
624#endif
625 return;
626} 898}
627 899
628 900
diff --git a/src/psycstore/gnunet-service-psycstore.c b/src/psycstore/gnunet-service-psycstore.c
index 7d27ea29b..87a2c87ab 100644
--- a/src/psycstore/gnunet-service-psycstore.c
+++ b/src/psycstore/gnunet-service-psycstore.c
@@ -25,6 +25,8 @@
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 */ 26 */
27 27
28#include <inttypes.h>
29
28#include "platform.h" 30#include "platform.h"
29#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
30#include "gnunet_constants.h" 32#include "gnunet_constants.h"
@@ -89,39 +91,41 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
89/** 91/**
90 * Send a result code back to the client. 92 * Send a result code back to the client.
91 * 93 *
92 * @param client Client that should receive the result code. 94 * @param client
93 * @param result_code Code to transmit. 95 * Client that should receive the result code.
94 * @param op_id Operation ID. 96 * @param result_code
95 * @param err_msg Error message to include (or NULL for none). 97 * Code to transmit.
98 * @param op_id
99 * Operation ID in network byte order.
100 * @param err_msg
101 * Error message to include (or NULL for none).
96 */ 102 */
97static void 103static void
98send_result_code (struct GNUNET_SERVER_Client *client, uint32_t result_code, 104send_result_code (struct GNUNET_SERVER_Client *client, uint64_t op_id,
99 uint32_t op_id, const char *err_msg) 105 int64_t result_code, const char *err_msg)
100{ 106{
101 struct OperationResult *res; 107 struct OperationResult *res;
102 size_t err_len; 108 size_t err_len = 0; // FIXME: maximum length
103 109
104 if (NULL == err_msg) 110 if (NULL != err_msg)
105 err_len = 0;
106 else
107 err_len = strlen (err_msg) + 1; 111 err_len = strlen (err_msg) + 1;
108 res = GNUNET_malloc (sizeof (struct OperationResult) + err_len); 112 res = GNUNET_malloc (sizeof (struct OperationResult) + err_len);
109 res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE); 113 res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE);
110 res->header.size = htons (sizeof (struct OperationResult) + err_len); 114 res->header.size = htons (sizeof (struct OperationResult) + err_len);
111 res->result_code = htonl (result_code); 115 res->result_code = GNUNET_htonll (result_code - INT64_MIN);
112 res->op_id = op_id; 116 res->op_id = op_id;
113 if (0 < err_len) 117 if (0 < err_len)
114 memcpy (&res[1], err_msg, err_len); 118 memcpy (&res[1], err_msg, err_len);
115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 119 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
116 "Sending result %d (%s) to client\n", 120 "Sending result to client: %" PRId64 " (%s)\n",
117 (int) result_code, 121 result_code, err_msg);
118 err_msg);
119 GNUNET_SERVER_notification_context_add (nc, client); 122 GNUNET_SERVER_notification_context_add (nc, client);
120 GNUNET_SERVER_notification_context_unicast (nc, client, &res->header, 123 GNUNET_SERVER_notification_context_unicast (nc, client, &res->header,
121 GNUNET_NO); 124 GNUNET_NO);
122 GNUNET_free (res); 125 GNUNET_free (res);
123} 126}
124 127
128
125enum 129enum
126{ 130{
127 MEMBERSHIP_TEST_NOT_NEEDED = 0, 131 MEMBERSHIP_TEST_NOT_NEEDED = 0,
@@ -129,6 +133,7 @@ enum
129 MEMBERSHIP_TEST_DONE = 2, 133 MEMBERSHIP_TEST_DONE = 2,
130} MessageMembershipTest; 134} MessageMembershipTest;
131 135
136
132struct SendClosure 137struct SendClosure
133{ 138{
134 struct GNUNET_SERVER_Client *client; 139 struct GNUNET_SERVER_Client *client;
@@ -158,7 +163,6 @@ struct SendClosure
158 * @see enum MessageMembershipTest 163 * @see enum MessageMembershipTest
159 */ 164 */
160 uint8_t membership_test; 165 uint8_t membership_test;
161
162}; 166};
163 167
164 168
@@ -214,6 +218,8 @@ send_state_var (void *cls, const char *name,
214 struct StateResult *res; 218 struct StateResult *res;
215 size_t name_size = strlen (name) + 1; 219 size_t name_size = strlen (name) + 1;
216 220
221 /* FIXME: split up value into 64k chunks */
222
217 res = GNUNET_malloc (sizeof (struct StateResult) + name_size + value_size); 223 res = GNUNET_malloc (sizeof (struct StateResult) + name_size + value_size);
218 res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_STATE); 224 res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_STATE);
219 res->header.size = htons (sizeof (struct StateResult) + name_size + value_size); 225 res->header.size = htons (sizeof (struct StateResult) + name_size + value_size);
@@ -249,7 +255,7 @@ handle_membership_store (void *cls,
249 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 255 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
250 _("Failed to store membership information!\n")); 256 _("Failed to store membership information!\n"));
251 257
252 send_result_code (client, ret, req->op_id, NULL); 258 send_result_code (client, req->op_id, ret, NULL);
253 GNUNET_SERVER_receive_done (client, GNUNET_OK); 259 GNUNET_SERVER_receive_done (client, GNUNET_OK);
254} 260}
255 261
@@ -274,7 +280,7 @@ handle_membership_test (void *cls,
274 _("Failed to test membership!\n")); 280 _("Failed to test membership!\n"));
275 } 281 }
276 282
277 send_result_code (client, ret, req->op_id, NULL); 283 send_result_code (client, req->op_id, ret, NULL);
278 GNUNET_SERVER_receive_done (client, GNUNET_OK); 284 GNUNET_SERVER_receive_done (client, GNUNET_OK);
279} 285}
280 286
@@ -295,7 +301,7 @@ handle_fragment_store (void *cls,
295 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 301 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
296 _("Failed to store fragment!\n")); 302 _("Failed to store fragment!\n"));
297 303
298 send_result_code (client, ret, req->op_id, NULL); 304 send_result_code (client, req->op_id, ret, NULL);
299 GNUNET_SERVER_receive_done (client, GNUNET_OK); 305 GNUNET_SERVER_receive_done (client, GNUNET_OK);
300} 306}
301 307
@@ -312,9 +318,20 @@ handle_fragment_get (void *cls,
312 .channel_key = req->channel_key, .slave_key = req->slave_key, 318 .channel_key = req->channel_key, .slave_key = req->slave_key,
313 .membership_test = req->do_membership_test }; 319 .membership_test = req->do_membership_test };
314 320
315 int ret = db->fragment_get (db->cls, &req->channel_key, 321 int64_t ret;
316 GNUNET_ntohll (req->fragment_id), 322 uint64_t ret_frags = 0;
317 &send_fragment, &sc); 323 uint64_t first_fragment_id = GNUNET_ntohll (req->first_fragment_id);
324 uint64_t last_fragment_id = GNUNET_ntohll (req->last_fragment_id);
325 uint64_t limit = GNUNET_ntohll (req->fragment_limit);
326
327 if (0 == limit)
328 ret = db->fragment_get (db->cls, &req->channel_key,
329 first_fragment_id, last_fragment_id,
330 &ret_frags, &send_fragment, &sc);
331 else
332 ret = db->fragment_get_latest (db->cls, &req->channel_key, limit,
333 &ret_frags, &send_fragment, &sc);
334
318 switch (ret) 335 switch (ret)
319 { 336 {
320 case GNUNET_YES: 337 case GNUNET_YES:
@@ -340,8 +357,7 @@ handle_fragment_get (void *cls,
340 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 357 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
341 _("Failed to get fragment!\n")); 358 _("Failed to get fragment!\n"));
342 } 359 }
343 360 send_result_code (client, req->op_id, (ret < 0) ? ret : ret_frags, NULL);
344 send_result_code (client, ret, req->op_id, NULL);
345 GNUNET_SERVER_receive_done (client, GNUNET_OK); 361 GNUNET_SERVER_receive_done (client, GNUNET_OK);
346} 362}
347 363
@@ -358,22 +374,31 @@ handle_message_get (void *cls,
358 .channel_key = req->channel_key, .slave_key = req->slave_key, 374 .channel_key = req->channel_key, .slave_key = req->slave_key,
359 .membership_test = req->do_membership_test }; 375 .membership_test = req->do_membership_test };
360 376
377 int64_t ret;
361 uint64_t ret_frags = 0; 378 uint64_t ret_frags = 0;
362 int64_t ret = db->message_get (db->cls, &req->channel_key, 379 uint64_t first_message_id = GNUNET_ntohll (req->first_message_id);
363 GNUNET_ntohll (req->message_id), 380 uint64_t last_message_id = GNUNET_ntohll (req->last_message_id);
364 &ret_frags, &send_fragment, &sc); 381 uint64_t limit = GNUNET_ntohll (req->message_limit);
382
383 if (0 == limit)
384 ret = db->message_get (db->cls, &req->channel_key,
385 first_message_id, last_message_id,
386 &ret_frags, &send_fragment, &sc);
387 else
388 ret = db->message_get_latest (db->cls, &req->channel_key, limit,
389 &ret_frags, &send_fragment, &sc);
390
365 switch (ret) 391 switch (ret)
366 { 392 {
367 case GNUNET_YES: 393 case GNUNET_YES:
368 case GNUNET_NO: 394 case GNUNET_NO:
369 break; 395 break;
370 default: 396 default:
371 ret_frags = ret;
372 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 397 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
373 _("Failed to get message!\n")); 398 _("Failed to get message!\n"));
374 } 399 }
375 400
376 send_result_code (client, ret_frags, req->op_id, NULL); 401 send_result_code (client, req->op_id, (ret < 0) ? ret : ret_frags, NULL);
377 GNUNET_SERVER_receive_done (client, GNUNET_OK); 402 GNUNET_SERVER_receive_done (client, GNUNET_OK);
378} 403}
379 404
@@ -404,7 +429,7 @@ handle_message_get_fragment (void *cls,
404 _("Failed to get message fragment!\n")); 429 _("Failed to get message fragment!\n"));
405 } 430 }
406 431
407 send_result_code (client, ret, req->op_id, NULL); 432 send_result_code (client, req->op_id, ret, NULL);
408 GNUNET_SERVER_receive_done (client, GNUNET_OK); 433 GNUNET_SERVER_receive_done (client, GNUNET_OK);
409} 434}
410 435
@@ -434,7 +459,7 @@ handle_counters_get (void *cls,
434 459
435 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS); 460 res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS);
436 res.header.size = htons (sizeof (res)); 461 res.header.size = htons (sizeof (res));
437 res.result_code = htonl (ret); 462 res.result_code = htonl (ret - INT32_MIN);
438 res.op_id = req->op_id; 463 res.op_id = req->op_id;
439 res.max_fragment_id = GNUNET_htonll (res.max_fragment_id); 464 res.max_fragment_id = GNUNET_htonll (res.max_fragment_id);
440 res.max_message_id = GNUNET_htonll (res.max_message_id); 465 res.max_message_id = GNUNET_htonll (res.max_message_id);
@@ -517,7 +542,7 @@ handle_state_modify (void *cls,
517 _("Failed to end modifying state!\n")); 542 _("Failed to end modifying state!\n"));
518 } 543 }
519 } 544 }
520 send_result_code (client, ret, req->op_id, NULL); 545 send_result_code (client, req->op_id, ret, NULL);
521 GNUNET_SERVER_receive_done (client, GNUNET_OK); 546 GNUNET_SERVER_receive_done (client, GNUNET_OK);
522} 547}
523 548
@@ -571,7 +596,7 @@ handle_state_sync (void *cls,
571 _("Failed to end synchronizing state!\n")); 596 _("Failed to end synchronizing state!\n"));
572 } 597 }
573 } 598 }
574 send_result_code (client, ret, req->op_id, NULL); 599 send_result_code (client, req->op_id, ret, NULL);
575 GNUNET_SERVER_receive_done (client, GNUNET_OK); 600 GNUNET_SERVER_receive_done (client, GNUNET_OK);
576} 601}
577 602
@@ -590,7 +615,7 @@ handle_state_reset (void *cls,
590 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 615 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
591 _("Failed to reset state!\n")); 616 _("Failed to reset state!\n"));
592 617
593 send_result_code (client, ret, req->op_id, NULL); 618 send_result_code (client, req->op_id, ret, NULL);
594 GNUNET_SERVER_receive_done (client, GNUNET_OK); 619 GNUNET_SERVER_receive_done (client, GNUNET_OK);
595} 620}
596 621
@@ -609,7 +634,7 @@ handle_state_hash_update (void *cls,
609 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 634 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
610 _("Failed to reset state!\n")); 635 _("Failed to reset state!\n"));
611 636
612 send_result_code (client, ret, req->op_id, NULL); 637 send_result_code (client, req->op_id, ret, NULL);
613 GNUNET_SERVER_receive_done (client, GNUNET_OK); 638 GNUNET_SERVER_receive_done (client, GNUNET_OK);
614} 639}
615 640
@@ -660,7 +685,7 @@ handle_state_get (void *cls,
660 _("Failed to get state variable!\n")); 685 _("Failed to get state variable!\n"));
661 } 686 }
662 687
663 send_result_code (client, ret, req->op_id, NULL); 688 send_result_code (client, req->op_id, ret, NULL);
664 GNUNET_SERVER_receive_done (client, GNUNET_OK); 689 GNUNET_SERVER_receive_done (client, GNUNET_OK);
665} 690}
666 691
@@ -699,7 +724,7 @@ handle_state_get_prefix (void *cls,
699 _("Failed to get state variable!\n")); 724 _("Failed to get state variable!\n"));
700 } 725 }
701 726
702 send_result_code (client, ret, req->op_id, NULL); 727 send_result_code (client, req->op_id, ret, NULL);
703 GNUNET_SERVER_receive_done (client, GNUNET_OK); 728 GNUNET_SERVER_receive_done (client, GNUNET_OK);
704} 729}
705 730
diff --git a/src/psycstore/plugin_psycstore_sqlite.c b/src/psycstore/plugin_psycstore_sqlite.c
index 86b969c5d..cb6c5c437 100644
--- a/src/psycstore/plugin_psycstore_sqlite.c
+++ b/src/psycstore/plugin_psycstore_sqlite.c
@@ -130,12 +130,22 @@ struct Plugin
130 /** 130 /**
131 * Precompiled SQL for fragment_get() 131 * Precompiled SQL for fragment_get()
132 */ 132 */
133 sqlite3_stmt *select_fragment; 133 sqlite3_stmt *select_fragments;
134
135 /**
136 * Precompiled SQL for fragment_get()
137 */
138 sqlite3_stmt *select_latest_fragments;
134 139
135 /** 140 /**
136 * Precompiled SQL for message_get() 141 * Precompiled SQL for message_get()
137 */ 142 */
138 sqlite3_stmt *select_message; 143 sqlite3_stmt *select_messages;
144
145 /**
146 * Precompiled SQL for message_get()
147 */
148 sqlite3_stmt *select_latest_messages;
139 149
140 /** 150 /**
141 * Precompiled SQL for message_get_fragment() 151 * Precompiled SQL for message_get_fragment()
@@ -456,8 +466,8 @@ database_setup (struct Plugin *plugin)
456 " multicast_flags, psycstore_flags, data\n" 466 " multicast_flags, psycstore_flags, data\n"
457 "FROM messages\n" 467 "FROM messages\n"
458 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" 468 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
459 " AND fragment_id = ?;", 469 " AND ? <= fragment_id AND fragment_id <= ?;",
460 &plugin->select_fragment); 470 &plugin->select_fragments);
461 471
462 sql_prepare (plugin->dbh, 472 sql_prepare (plugin->dbh,
463 "SELECT hop_counter, signature, purpose, fragment_id,\n" 473 "SELECT hop_counter, signature, purpose, fragment_id,\n"
@@ -465,8 +475,35 @@ database_setup (struct Plugin *plugin)
465 " multicast_flags, psycstore_flags, data\n" 475 " multicast_flags, psycstore_flags, data\n"
466 "FROM messages\n" 476 "FROM messages\n"
467 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" 477 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
468 " AND message_id = ? AND fragment_offset = ?;", 478 " AND ? <= message_id AND message_id <= ?;",
469 &plugin->select_message_fragment); 479 &plugin->select_messages);
480
481 sql_prepare (plugin->dbh,
482 "SELECT * FROM\n"
483 "(SELECT hop_counter, signature, purpose, fragment_id,\n"
484 " fragment_offset, message_id, group_generation,\n"
485 " multicast_flags, psycstore_flags, data\n"
486 " FROM messages\n"
487 " WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
488 " ORDER BY fragment_id DESC\n"
489 " LIMIT ?)\n"
490 "ORDER BY fragment_id;",
491 &plugin->select_latest_fragments);
492
493 sql_prepare (plugin->dbh,
494 "SELECT hop_counter, signature, purpose, fragment_id,\n"
495 " fragment_offset, message_id, group_generation,\n"
496 " multicast_flags, psycstore_flags, data\n"
497 "FROM messages\n"
498 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
499 " AND message_id IN\n"
500 " (SELECT message_id\n"
501 " FROM messages\n"
502 " WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
503 " ORDER BY message_id\n"
504 " DESC LIMIT ?)\n"
505 "ORDER BY fragment_id;",
506 &plugin->select_latest_messages);
470 507
471 sql_prepare (plugin->dbh, 508 sql_prepare (plugin->dbh,
472 "SELECT hop_counter, signature, purpose, fragment_id,\n" 509 "SELECT hop_counter, signature, purpose, fragment_id,\n"
@@ -474,8 +511,8 @@ database_setup (struct Plugin *plugin)
474 " multicast_flags, psycstore_flags, data\n" 511 " multicast_flags, psycstore_flags, data\n"
475 "FROM messages\n" 512 "FROM messages\n"
476 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" 513 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
477 " AND message_id = ?;", 514 " AND message_id = ? AND fragment_offset = ?;",
478 &plugin->select_message); 515 &plugin->select_message_fragment);
479 516
480 sql_prepare (plugin->dbh, 517 sql_prepare (plugin->dbh,
481 "SELECT fragment_id, message_id, group_generation\n" 518 "SELECT fragment_id, message_id, group_generation\n"
@@ -1036,8 +1073,42 @@ fragment_row (sqlite3_stmt *stmt, GNUNET_PSYCSTORE_FragmentCallback cb,
1036 return cb (cb_cls, (void *) msg, sqlite3_column_int64 (stmt, 8)); 1073 return cb (cb_cls, (void *) msg, sqlite3_column_int64 (stmt, 8));
1037} 1074}
1038 1075
1076
1077static int
1078fragment_select (struct Plugin *plugin, sqlite3_stmt *stmt,
1079 uint64_t *returned_fragments,
1080 GNUNET_PSYCSTORE_FragmentCallback cb, void *cb_cls)
1081{
1082 int ret = GNUNET_SYSERR;
1083 int sql_ret;
1084
1085 do
1086 {
1087 sql_ret = sqlite3_step (stmt);
1088 switch (sql_ret)
1089 {
1090 case SQLITE_DONE:
1091 if (ret != GNUNET_OK)
1092 ret = GNUNET_NO;
1093 break;
1094 case SQLITE_ROW:
1095 ret = fragment_row (stmt, cb, cb_cls);
1096 (*returned_fragments)++;
1097 if (ret != GNUNET_YES)
1098 sql_ret = SQLITE_DONE;
1099 break;
1100 default:
1101 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1102 "sqlite3_step");
1103 }
1104 }
1105 while (sql_ret == SQLITE_ROW);
1106
1107 return ret;
1108}
1109
1039/** 1110/**
1040 * Retrieve a message fragment by fragment ID. 1111 * Retrieve a message fragment range by fragment ID.
1041 * 1112 *
1042 * @see GNUNET_PSYCSTORE_fragment_get() 1113 * @see GNUNET_PSYCSTORE_fragment_get()
1043 * 1114 *
@@ -1046,36 +1117,29 @@ fragment_row (sqlite3_stmt *stmt, GNUNET_PSYCSTORE_FragmentCallback cb,
1046static int 1117static int
1047fragment_get (void *cls, 1118fragment_get (void *cls,
1048 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, 1119 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1049 uint64_t fragment_id, 1120 uint64_t first_fragment_id,
1121 uint64_t last_fragment_id,
1122 uint64_t *returned_fragments,
1050 GNUNET_PSYCSTORE_FragmentCallback cb, 1123 GNUNET_PSYCSTORE_FragmentCallback cb,
1051 void *cb_cls) 1124 void *cb_cls)
1052{ 1125{
1053 struct Plugin *plugin = cls; 1126 struct Plugin *plugin = cls;
1054 sqlite3_stmt *stmt = plugin->select_fragment; 1127 sqlite3_stmt *stmt = plugin->select_fragments;
1055 int ret = GNUNET_SYSERR; 1128 int ret = GNUNET_SYSERR;
1129 *returned_fragments = 0;
1056 1130
1057 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, 1131 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1058 sizeof (*channel_key), 1132 sizeof (*channel_key),
1059 SQLITE_STATIC) 1133 SQLITE_STATIC)
1060 || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, fragment_id)) 1134 || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, first_fragment_id)
1135 || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, last_fragment_id))
1061 { 1136 {
1062 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 1137 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1063 "sqlite3_bind"); 1138 "sqlite3_bind");
1064 } 1139 }
1065 else 1140 else
1066 { 1141 {
1067 switch (sqlite3_step (stmt)) 1142 ret = fragment_select (plugin, stmt, returned_fragments, cb, cb_cls);
1068 {
1069 case SQLITE_DONE:
1070 ret = GNUNET_NO;
1071 break;
1072 case SQLITE_ROW:
1073 ret = fragment_row (stmt, cb, cb_cls);
1074 break;
1075 default:
1076 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1077 "sqlite3_step");
1078 }
1079 } 1143 }
1080 1144
1081 if (SQLITE_OK != sqlite3_reset (stmt)) 1145 if (SQLITE_OK != sqlite3_reset (stmt))
@@ -1087,8 +1151,52 @@ fragment_get (void *cls,
1087 return ret; 1151 return ret;
1088} 1152}
1089 1153
1154
1090/** 1155/**
1091 * Retrieve all fragments of a message. 1156 * Retrieve a message fragment range by fragment ID.
1157 *
1158 * @see GNUNET_PSYCSTORE_fragment_get_latest()
1159 *
1160 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1161 */
1162static int
1163fragment_get_latest (void *cls,
1164 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1165 uint64_t fragment_limit,
1166 uint64_t *returned_fragments,
1167 GNUNET_PSYCSTORE_FragmentCallback cb,
1168 void *cb_cls)
1169{
1170 struct Plugin *plugin = cls;
1171 sqlite3_stmt *stmt = plugin->select_latest_fragments;
1172 int ret = GNUNET_SYSERR;
1173 *returned_fragments = 0;
1174
1175 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1176 sizeof (*channel_key),
1177 SQLITE_STATIC)
1178 || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, fragment_limit))
1179 {
1180 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1181 "sqlite3_bind");
1182 }
1183 else
1184 {
1185 ret = fragment_select (plugin, stmt, returned_fragments, cb, cb_cls);
1186 }
1187
1188 if (SQLITE_OK != sqlite3_reset (stmt))
1189 {
1190 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1191 "sqlite3_reset");
1192 }
1193
1194 return ret;
1195}
1196
1197
1198/**
1199 * Retrieve all fragments of a message ID range.
1092 * 1200 *
1093 * @see GNUNET_PSYCSTORE_message_get() 1201 * @see GNUNET_PSYCSTORE_message_get()
1094 * 1202 *
@@ -1097,48 +1205,29 @@ fragment_get (void *cls,
1097static int 1205static int
1098message_get (void *cls, 1206message_get (void *cls,
1099 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, 1207 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1100 uint64_t message_id, 1208 uint64_t first_message_id,
1209 uint64_t last_message_id,
1101 uint64_t *returned_fragments, 1210 uint64_t *returned_fragments,
1102 GNUNET_PSYCSTORE_FragmentCallback cb, 1211 GNUNET_PSYCSTORE_FragmentCallback cb,
1103 void *cb_cls) 1212 void *cb_cls)
1104{ 1213{
1105 struct Plugin *plugin = cls; 1214 struct Plugin *plugin = cls;
1106 sqlite3_stmt *stmt = plugin->select_message; 1215 sqlite3_stmt *stmt = plugin->select_messages;
1107 int ret = GNUNET_SYSERR; 1216 int ret = GNUNET_SYSERR;
1108 *returned_fragments = 0; 1217 *returned_fragments = 0;
1109 1218
1110 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, 1219 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1111 sizeof (*channel_key), 1220 sizeof (*channel_key),
1112 SQLITE_STATIC) 1221 SQLITE_STATIC)
1113 || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, message_id)) 1222 || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, first_message_id)
1223 || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, last_message_id))
1114 { 1224 {
1115 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 1225 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1116 "sqlite3_bind"); 1226 "sqlite3_bind");
1117 } 1227 }
1118 else 1228 else
1119 { 1229 {
1120 int sql_ret; 1230 ret = fragment_select (plugin, stmt, returned_fragments, cb, cb_cls);
1121 do
1122 {
1123 sql_ret = sqlite3_step (stmt);
1124 switch (sql_ret)
1125 {
1126 case SQLITE_DONE:
1127 if (ret != GNUNET_OK)
1128 ret = GNUNET_NO;
1129 break;
1130 case SQLITE_ROW:
1131 ret = fragment_row (stmt, cb, cb_cls);
1132 (*returned_fragments)++;
1133 if (ret != GNUNET_YES)
1134 sql_ret = SQLITE_DONE;
1135 break;
1136 default:
1137 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1138 "sqlite3_step");
1139 }
1140 }
1141 while (sql_ret == SQLITE_ROW);
1142 } 1231 }
1143 1232
1144 if (SQLITE_OK != sqlite3_reset (stmt)) 1233 if (SQLITE_OK != sqlite3_reset (stmt))
@@ -1150,6 +1239,53 @@ message_get (void *cls,
1150 return ret; 1239 return ret;
1151} 1240}
1152 1241
1242
1243/**
1244 * Retrieve all fragments of the latest messages.
1245 *
1246 * @see GNUNET_PSYCSTORE_message_get_latest()
1247 *
1248 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1249 */
1250static int
1251message_get_latest (void *cls,
1252 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1253 uint64_t message_limit,
1254 uint64_t *returned_fragments,
1255 GNUNET_PSYCSTORE_FragmentCallback cb,
1256 void *cb_cls)
1257{
1258 struct Plugin *plugin = cls;
1259 sqlite3_stmt *stmt = plugin->select_latest_messages;
1260 int ret = GNUNET_SYSERR;
1261 *returned_fragments = 0;
1262
1263 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1264 sizeof (*channel_key),
1265 SQLITE_STATIC)
1266 || SQLITE_OK != sqlite3_bind_blob (stmt, 2, channel_key,
1267 sizeof (*channel_key),
1268 SQLITE_STATIC)
1269 || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, message_limit))
1270 {
1271 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1272 "sqlite3_bind");
1273 }
1274 else
1275 {
1276 ret = fragment_select (plugin, stmt, returned_fragments, cb, cb_cls);
1277 }
1278
1279 if (SQLITE_OK != sqlite3_reset (stmt))
1280 {
1281 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1282 "sqlite3_reset");
1283 }
1284
1285 return ret;
1286}
1287
1288
1153/** 1289/**
1154 * Retrieve a fragment of message specified by its message ID and fragment 1290 * Retrieve a fragment of message specified by its message ID and fragment
1155 * offset. 1291 * offset.
@@ -1777,7 +1913,9 @@ libgnunet_plugin_psycstore_sqlite_init (void *cls)
1777 api->fragment_store = &fragment_store; 1913 api->fragment_store = &fragment_store;
1778 api->message_add_flags = &message_add_flags; 1914 api->message_add_flags = &message_add_flags;
1779 api->fragment_get = &fragment_get; 1915 api->fragment_get = &fragment_get;
1916 api->fragment_get_latest = &fragment_get_latest;
1780 api->message_get = &message_get; 1917 api->message_get = &message_get;
1918 api->message_get_latest = &message_get_latest;
1781 api->message_get_fragment = &message_get_fragment; 1919 api->message_get_fragment = &message_get_fragment;
1782 api->counters_message_get = &counters_message_get; 1920 api->counters_message_get = &counters_message_get;
1783 api->counters_state_get = &counters_state_get; 1921 api->counters_state_get = &counters_state_get;
diff --git a/src/psycstore/psycstore.h b/src/psycstore/psycstore.h
index 17905f422..e6a82848a 100644
--- a/src/psycstore/psycstore.h
+++ b/src/psycstore/psycstore.h
@@ -42,15 +42,17 @@ struct OperationResult
42 */ 42 */
43 struct GNUNET_MessageHeader header; 43 struct GNUNET_MessageHeader header;
44 44
45 uint32_t reserved GNUNET_PACKED;
46
45 /** 47 /**
46 * Operation ID. 48 * Operation ID.
47 */ 49 */
48 uint32_t op_id GNUNET_PACKED; 50 uint64_t op_id GNUNET_PACKED;
49 51
50 /** 52 /**
51 * Status code for the operation. 53 * Status code for the operation.
52 */ 54 */
53 int64_t result_code GNUNET_PACKED; 55 uint64_t result_code GNUNET_PACKED;
54 56
55 /* followed by 0-terminated error message (on error) */ 57 /* followed by 0-terminated error message (on error) */
56 58
@@ -70,9 +72,17 @@ struct CountersResult
70 struct GNUNET_MessageHeader header; 72 struct GNUNET_MessageHeader header;
71 73
72 /** 74 /**
75 * Status code for the operation:
76 * #GNUNET_OK: success, counter values are returned.
77 * #GNUNET_NO: no message has been sent to the channel yet.
78 * #GNUNET_SYSERR: an error occurred.
79 */
80 uint32_t result_code GNUNET_PACKED;
81
82 /**
73 * Operation ID. 83 * Operation ID.
74 */ 84 */
75 uint32_t op_id GNUNET_PACKED; 85 uint64_t op_id GNUNET_PACKED;
76 86
77 uint64_t max_fragment_id GNUNET_PACKED; 87 uint64_t max_fragment_id GNUNET_PACKED;
78 88
@@ -81,14 +91,6 @@ struct CountersResult
81 uint64_t max_group_generation GNUNET_PACKED; 91 uint64_t max_group_generation GNUNET_PACKED;
82 92
83 uint64_t max_state_message_id GNUNET_PACKED; 93 uint64_t max_state_message_id GNUNET_PACKED;
84
85 /**
86 * Status code for the operation:
87 * #GNUNET_OK: success, counter values are returned.
88 * #GNUNET_NO: no message has been sent to the channel yet.
89 * #GNUNET_SYSERR: an error occurred.
90 */
91 int32_t result_code GNUNET_PACKED;
92}; 94};
93 95
94 96
@@ -102,15 +104,14 @@ struct FragmentResult
102 */ 104 */
103 struct GNUNET_MessageHeader header; 105 struct GNUNET_MessageHeader header;
104 106
107 uint32_t psycstore_flags GNUNET_PACKED;
108
105 /** 109 /**
106 * Operation ID. 110 * Operation ID.
107 */ 111 */
108 uint32_t op_id GNUNET_PACKED; 112 uint64_t op_id GNUNET_PACKED;
109
110 uint32_t psycstore_flags GNUNET_PACKED;
111
112 /* followed by GNUNET_MULTICAST_MessageHeader */
113 113
114 /* Followed by GNUNET_MULTICAST_MessageHeader */
114}; 115};
115 116
116 117
@@ -124,14 +125,16 @@ struct StateResult
124 */ 125 */
125 struct GNUNET_MessageHeader header; 126 struct GNUNET_MessageHeader header;
126 127
128 uint16_t name_size GNUNET_PACKED;
129
130 uint16_t reserved GNUNET_PACKED;
131
127 /** 132 /**
128 * Operation ID. 133 * Operation ID.
129 */ 134 */
130 uint32_t op_id GNUNET_PACKED; 135 uint64_t op_id GNUNET_PACKED;
131
132 uint16_t name_size GNUNET_PACKED;
133 136
134 /* followed by name and value */ 137 /* Followed by name and value */
135}; 138};
136 139
137 140
@@ -142,13 +145,14 @@ struct OperationRequest
142{ 145{
143 struct GNUNET_MessageHeader header; 146 struct GNUNET_MessageHeader header;
144 147
148 uint32_t reserved GNUNET_PACKED;
149
145 /** 150 /**
146 * Operation ID. 151 * Operation ID.
147 */ 152 */
148 uint32_t op_id GNUNET_PACKED; 153 uint64_t op_id GNUNET_PACKED;
149 154
150 struct GNUNET_CRYPTO_EddsaPublicKey channel_key; 155 struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
151
152}; 156};
153 157
154 158
@@ -162,10 +166,12 @@ struct MembershipStoreRequest
162 */ 166 */
163 struct GNUNET_MessageHeader header; 167 struct GNUNET_MessageHeader header;
164 168
169 uint32_t reserved GNUNET_PACKED;
170
165 /** 171 /**
166 * Operation ID. 172 * Operation ID.
167 */ 173 */
168 uint32_t op_id GNUNET_PACKED; 174 uint64_t op_id GNUNET_PACKED;
169 175
170 /** 176 /**
171 * Channel's public key. 177 * Channel's public key.
@@ -177,9 +183,9 @@ struct MembershipStoreRequest
177 */ 183 */
178 struct GNUNET_CRYPTO_EcdsaPublicKey slave_key; 184 struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
179 185
180 uint64_t announced_at; 186 uint64_t announced_at GNUNET_PACKED;
181 uint64_t effective_since; 187 uint64_t effective_since GNUNET_PACKED;
182 uint64_t group_generation; 188 uint64_t group_generation GNUNET_PACKED;
183 uint8_t did_join; 189 uint8_t did_join;
184}; 190};
185 191
@@ -194,10 +200,12 @@ struct MembershipTestRequest
194 */ 200 */
195 struct GNUNET_MessageHeader header; 201 struct GNUNET_MessageHeader header;
196 202
203 uint32_t reserved GNUNET_PACKED;
204
197 /** 205 /**
198 * Operation ID. 206 * Operation ID.
199 */ 207 */
200 uint32_t op_id GNUNET_PACKED; 208 uint64_t op_id GNUNET_PACKED;
201 209
202 /** 210 /**
203 * Channel's public key. 211 * Channel's public key.
@@ -226,9 +234,9 @@ struct FragmentStoreRequest
226 struct GNUNET_MessageHeader header; 234 struct GNUNET_MessageHeader header;
227 235
228 /** 236 /**
229 * Operation ID. 237 * enum GNUNET_PSYCSTORE_MessageFlags
230 */ 238 */
231 uint32_t op_id GNUNET_PACKED; 239 uint32_t psycstore_flags GNUNET_PACKED;
232 240
233 /** 241 /**
234 * Channel's public key. 242 * Channel's public key.
@@ -236,9 +244,9 @@ struct FragmentStoreRequest
236 struct GNUNET_CRYPTO_EddsaPublicKey channel_key; 244 struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
237 245
238 /** 246 /**
239 * enum GNUNET_PSYCSTORE_MessageFlags 247 * Operation ID.
240 */ 248 */
241 uint32_t psycstore_flags GNUNET_PACKED; 249 uint64_t op_id;
242 250
243 /* Followed by fragment */ 251 /* Followed by fragment */
244}; 252};
@@ -254,10 +262,12 @@ struct FragmentGetRequest
254 */ 262 */
255 struct GNUNET_MessageHeader header; 263 struct GNUNET_MessageHeader header;
256 264
265 uint32_t reserved GNUNET_PACKED;
266
257 /** 267 /**
258 * Operation ID. 268 * Operation ID.
259 */ 269 */
260 uint32_t op_id GNUNET_PACKED; 270 uint64_t op_id GNUNET_PACKED;
261 271
262 /** 272 /**
263 * Channel's public key. 273 * Channel's public key.
@@ -270,9 +280,19 @@ struct FragmentGetRequest
270 struct GNUNET_CRYPTO_EcdsaPublicKey slave_key; 280 struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
271 281
272 /** 282 /**
273 * Fragment ID to request. 283 * First fragment ID to request.
274 */ 284 */
275 uint64_t fragment_id GNUNET_PACKED; 285 uint64_t first_fragment_id GNUNET_PACKED;
286
287 /**
288 * Last fragment ID to request.
289 */
290 uint64_t last_fragment_id GNUNET_PACKED;
291
292 /**
293 * Maximum number of fragments to retrieve.
294 */
295 uint64_t fragment_limit GNUNET_PACKED;
276 296
277 /** 297 /**
278 * Do membership test with @a slave_key before returning fragment? 298 * Do membership test with @a slave_key before returning fragment?
@@ -292,10 +312,12 @@ struct MessageGetRequest
292 */ 312 */
293 struct GNUNET_MessageHeader header; 313 struct GNUNET_MessageHeader header;
294 314
315 uint32_t reserved GNUNET_PACKED;
316
295 /** 317 /**
296 * Operation ID. 318 * Operation ID.
297 */ 319 */
298 uint32_t op_id GNUNET_PACKED; 320 uint64_t op_id GNUNET_PACKED;
299 321
300 /** 322 /**
301 * Channel's public key. 323 * Channel's public key.
@@ -308,9 +330,19 @@ struct MessageGetRequest
308 struct GNUNET_CRYPTO_EcdsaPublicKey slave_key; 330 struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
309 331
310 /** 332 /**
311 * Message ID to request. 333 * First message ID to request.
312 */ 334 */
313 uint64_t message_id GNUNET_PACKED; 335 uint64_t first_message_id GNUNET_PACKED;
336
337 /**
338 * Last message ID to request.
339 */
340 uint64_t last_message_id GNUNET_PACKED;
341
342 /**
343 * Maximum number of messages to retrieve.
344 */
345 uint64_t message_limit GNUNET_PACKED;
314 346
315 /** 347 /**
316 * Do membership test with @a slave_key before returning fragment? 348 * Do membership test with @a slave_key before returning fragment?
@@ -330,10 +362,12 @@ struct MessageGetFragmentRequest
330 */ 362 */
331 struct GNUNET_MessageHeader header; 363 struct GNUNET_MessageHeader header;
332 364
365 uint32_t reserved GNUNET_PACKED;
366
333 /** 367 /**
334 * Operation ID. 368 * Operation ID.
335 */ 369 */
336 uint32_t op_id GNUNET_PACKED; 370 uint64_t op_id GNUNET_PACKED;
337 371
338 /** 372 /**
339 * Channel's public key. 373 * Channel's public key.
@@ -373,10 +407,12 @@ struct StateHashUpdateRequest
373 */ 407 */
374 struct GNUNET_MessageHeader header; 408 struct GNUNET_MessageHeader header;
375 409
410 uint32_t reserved GNUNET_PACKED;
411
376 /** 412 /**
377 * Operation ID. 413 * Operation ID.
378 */ 414 */
379 uint32_t op_id GNUNET_PACKED; 415 uint64_t op_id GNUNET_PACKED;
380 416
381 /** 417 /**
382 * Channel's public key. 418 * Channel's public key.
@@ -405,20 +441,6 @@ struct StateModifyRequest
405 struct GNUNET_MessageHeader header; 441 struct GNUNET_MessageHeader header;
406 442
407 /** 443 /**
408 * Operation ID.
409 */
410 uint32_t op_id GNUNET_PACKED;
411
412 /**
413 * Channel's public key.
414 */
415 struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
416
417 uint64_t message_id GNUNET_PACKED;
418
419 uint64_t state_delta GNUNET_PACKED;
420
421 /**
422 * Size of name, including NUL terminator. 444 * Size of name, including NUL terminator.
423 */ 445 */
424 uint16_t name_size GNUNET_PACKED; 446 uint16_t name_size GNUNET_PACKED;
@@ -433,6 +455,20 @@ struct StateModifyRequest
433 */ 455 */
434 uint8_t oper; 456 uint8_t oper;
435 457
458 /**
459 * Operation ID.
460 */
461 uint64_t op_id GNUNET_PACKED;
462
463 /**
464 * Channel's public key.
465 */
466 struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
467
468 uint64_t message_id GNUNET_PACKED;
469
470 uint64_t state_delta GNUNET_PACKED;
471
436 /* Followed by NUL-terminated name, then the value. */ 472 /* Followed by NUL-terminated name, then the value. */
437}; 473};
438 474
@@ -448,26 +484,28 @@ struct StateSyncRequest
448 struct GNUNET_MessageHeader header; 484 struct GNUNET_MessageHeader header;
449 485
450 /** 486 /**
451 * Operation ID. 487 * Size of name, including NUL terminator.
452 */ 488 */
453 uint32_t op_id GNUNET_PACKED; 489 uint16_t name_size GNUNET_PACKED;
454 490
455 /** 491 /**
456 * Channel's public key. 492 * OR'd StateOpFlags
457 */ 493 */
458 struct GNUNET_CRYPTO_EddsaPublicKey channel_key; 494 uint8_t flags;
495
496 uint8_t reserved;
459 497
460 uint64_t message_id GNUNET_PACKED; 498 uint64_t message_id GNUNET_PACKED;
461 499
462 /** 500 /**
463 * Size of name, including NUL terminator. 501 * Operation ID.
464 */ 502 */
465 uint16_t name_size GNUNET_PACKED; 503 uint64_t op_id GNUNET_PACKED;
466 504
467 /** 505 /**
468 * OR'd StateOpFlags 506 * Channel's public key.
469 */ 507 */
470 uint8_t flags; 508 struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
471 509
472 /* Followed by NUL-terminated name, then the value. */ 510 /* Followed by NUL-terminated name, then the value. */
473}; 511};
diff --git a/src/psycstore/psycstore_api.c b/src/psycstore/psycstore_api.c
index 9df55888d..9ef1fb61a 100644
--- a/src/psycstore/psycstore_api.c
+++ b/src/psycstore/psycstore_api.c
@@ -25,6 +25,8 @@
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 */ 26 */
27 27
28#include <inttypes.h>
29
28#include "platform.h" 30#include "platform.h"
29#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
30#include "gnunet_constants.h" 32#include "gnunet_constants.h"
@@ -76,7 +78,7 @@ struct GNUNET_PSYCSTORE_OperationHandle
76 /** 78 /**
77 * Operation ID. 79 * Operation ID.
78 */ 80 */
79 uint32_t op_id; 81 uint64_t op_id;
80 82
81 /** 83 /**
82 * Message to send to the PSYCstore service. 84 * Message to send to the PSYCstore service.
@@ -137,15 +139,14 @@ struct GNUNET_PSYCSTORE_Handle
137 struct GNUNET_TIME_Relative reconnect_delay; 139 struct GNUNET_TIME_Relative reconnect_delay;
138 140
139 /** 141 /**
140 * Are we polling for incoming messages right now? 142 * Last operation ID used.
141 */ 143 */
142 int in_receive; 144 uint64_t last_op_id;
143 145
144 /** 146 /**
145 * The last operation id used for a PSYCstore operation. 147 * Are we polling for incoming messages right now?
146 */ 148 */
147 uint32_t last_op_id_used; 149 uint8_t in_receive;
148
149}; 150};
150 151
151 152
@@ -155,10 +156,10 @@ struct GNUNET_PSYCSTORE_Handle
155 * @param h Handle to the PSYCstore service. 156 * @param h Handle to the PSYCstore service.
156 * @return next operation id to use 157 * @return next operation id to use
157 */ 158 */
158static uint32_t 159static uint64_t
159get_next_op_id (struct GNUNET_PSYCSTORE_Handle *h) 160get_next_op_id (struct GNUNET_PSYCSTORE_Handle *h)
160{ 161{
161 return h->last_op_id_used++; 162 return h->last_op_id++;
162} 163}
163 164
164 165
@@ -168,7 +169,7 @@ get_next_op_id (struct GNUNET_PSYCSTORE_Handle *h)
168 * @return OperationHandle if found, or NULL otherwise. 169 * @return OperationHandle if found, or NULL otherwise.
169 */ 170 */
170static struct GNUNET_PSYCSTORE_OperationHandle * 171static struct GNUNET_PSYCSTORE_OperationHandle *
171find_op_by_id (struct GNUNET_PSYCSTORE_Handle *h, uint32_t op_id) 172find_op_by_id (struct GNUNET_PSYCSTORE_Handle *h, uint64_t op_id)
172{ 173{
173 struct GNUNET_PSYCSTORE_OperationHandle *op = h->op_head; 174 struct GNUNET_PSYCSTORE_OperationHandle *op = h->op_head;
174 while (NULL != op) 175 while (NULL != op)
@@ -284,19 +285,20 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
284 if (size == sizeof (struct OperationResult)) 285 if (size == sizeof (struct OperationResult))
285 str = NULL; 286 str = NULL;
286 287
287 op = find_op_by_id (h, ntohl (opres->op_id)); 288 op = find_op_by_id (h, GNUNET_ntohll (opres->op_id));
288 if (NULL == op) 289 if (NULL == op)
289 { 290 {
290 LOG (GNUNET_ERROR_TYPE_DEBUG, 291 LOG (GNUNET_ERROR_TYPE_DEBUG,
291 "No callback registered for operation with ID %ld.\n", 292 "No callback registered for operation with ID %" PRIu64 ".\n",
292 type, ntohl (opres->op_id)); 293 type, GNUNET_ntohll (opres->op_id));
293 } 294 }
294 else 295 else
295 { 296 {
296 LOG (GNUNET_ERROR_TYPE_DEBUG, 297 LOG (GNUNET_ERROR_TYPE_DEBUG,
297 "Received result message (type %d) with operation ID: %ld\n", 298 "Received result message (type %d) with operation ID: %" PRIu64 "\n",
298 type, op->op_id); 299 type, op->op_id);
299 300
301 int64_t result_code = GNUNET_ntohll (opres->result_code) + INT64_MIN;
300 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); 302 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
301 if (NULL != op->res_cb) 303 if (NULL != op->res_cb)
302 { 304 {
@@ -307,19 +309,19 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
307 case GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY: 309 case GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY:
308 smreq = (const struct StateModifyRequest *) op->msg; 310 smreq = (const struct StateModifyRequest *) op->msg;
309 if (!(smreq->flags & STATE_OP_LAST 311 if (!(smreq->flags & STATE_OP_LAST
310 || GNUNET_OK != ntohl (opres->result_code))) 312 || GNUNET_OK != result_code))
311 op->res_cb = NULL; 313 op->res_cb = NULL;
312 break; 314 break;
313 case GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC: 315 case GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC:
314 ssreq = (const struct StateSyncRequest *) op->msg; 316 ssreq = (const struct StateSyncRequest *) op->msg;
315 if (!(ssreq->flags & STATE_OP_LAST 317 if (!(ssreq->flags & STATE_OP_LAST
316 || GNUNET_OK != ntohl (opres->result_code))) 318 || GNUNET_OK != result_code))
317 op->res_cb = NULL; 319 op->res_cb = NULL;
318 break; 320 break;
319 } 321 }
320 } 322 }
321 if (NULL != op->res_cb) 323 if (NULL != op->res_cb)
322 op->res_cb (op->cls, ntohl (opres->result_code), str); 324 op->res_cb (op->cls, result_code, str);
323 GNUNET_free (op); 325 GNUNET_free (op);
324 } 326 }
325 break; 327 break;
@@ -338,19 +340,20 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
338 340
339 cres = (const struct CountersResult *) msg; 341 cres = (const struct CountersResult *) msg;
340 342
341 op = find_op_by_id (h, ntohl (cres->op_id)); 343 op = find_op_by_id (h, GNUNET_ntohll (cres->op_id));
342 if (NULL == op) 344 if (NULL == op)
343 { 345 {
344 LOG (GNUNET_ERROR_TYPE_DEBUG, 346 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "No callback registered for operation with ID %ld.\n", 347 "No callback registered for operation with ID %" PRIu64 ".\n",
346 type, ntohl (cres->op_id)); 348 type, GNUNET_ntohll (cres->op_id));
347 } 349 }
348 else 350 else
349 { 351 {
350 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); 352 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
351 if (NULL != op->data_cb) 353 if (NULL != op->data_cb)
352 ((GNUNET_PSYCSTORE_CountersCallback) 354 ((GNUNET_PSYCSTORE_CountersCallback)
353 op->data_cb) (op->cls, ntohl (cres->result_code), 355 op->data_cb) (op->cls,
356 ntohl (cres->result_code) + INT32_MIN,
354 GNUNET_ntohll (cres->max_fragment_id), 357 GNUNET_ntohll (cres->max_fragment_id),
355 GNUNET_ntohll (cres->max_message_id), 358 GNUNET_ntohll (cres->max_message_id),
356 GNUNET_ntohll (cres->max_group_generation), 359 GNUNET_ntohll (cres->max_group_generation),
@@ -386,12 +389,12 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
386 return; 389 return;
387 } 390 }
388 391
389 op = find_op_by_id (h, ntohl (fres->op_id)); 392 op = find_op_by_id (h, GNUNET_ntohll (fres->op_id));
390 if (NULL == op) 393 if (NULL == op)
391 { 394 {
392 LOG (GNUNET_ERROR_TYPE_DEBUG, 395 LOG (GNUNET_ERROR_TYPE_DEBUG,
393 "No callback registered for operation with ID %ld.\n", 396 "No callback registered for operation with ID %" PRIu64 ".\n",
394 type, ntohl (fres->op_id)); 397 type, GNUNET_ntohll (fres->op_id));
395 } 398 }
396 else 399 else
397 { 400 {
@@ -427,12 +430,12 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
427 return; 430 return;
428 } 431 }
429 432
430 op = find_op_by_id (h, ntohl (sres->op_id)); 433 op = find_op_by_id (h, GNUNET_ntohll (sres->op_id));
431 if (NULL == op) 434 if (NULL == op)
432 { 435 {
433 LOG (GNUNET_ERROR_TYPE_DEBUG, 436 LOG (GNUNET_ERROR_TYPE_DEBUG,
434 "No callback registered for operation with ID %ld.\n", 437 "No callback registered for operation with ID %" PRIu64 ".\n",
435 type, ntohl (sres->op_id)); 438 type, GNUNET_ntohll (sres->op_id));
436 } 439 }
437 else 440 else
438 { 441 {
@@ -479,7 +482,7 @@ send_next_message (void *cls, size_t size, void *buf)
479 return 0; 482 return 0;
480 } 483 }
481 LOG (GNUNET_ERROR_TYPE_DEBUG, 484 LOG (GNUNET_ERROR_TYPE_DEBUG,
482 "Sending message of type %d to PSYCstore service. ID: %u\n", 485 "Sending message of type %d to PSYCstore service. ID: %" PRIu64 "\n",
483 ntohs (op->msg->type), op->op_id); 486 ntohs (op->msg->type), op->op_id);
484 memcpy (buf, op->msg, ret); 487 memcpy (buf, op->msg, ret);
485 488
@@ -682,8 +685,8 @@ GNUNET_PSYCSTORE_membership_store (struct GNUNET_PSYCSTORE_Handle *h,
682 : effective_since == 0); 685 : effective_since == 0);
683 686
684 struct MembershipStoreRequest *req; 687 struct MembershipStoreRequest *req;
685 struct GNUNET_PSYCSTORE_OperationHandle *op 688 struct GNUNET_PSYCSTORE_OperationHandle *
686 = GNUNET_malloc (sizeof (*op) + sizeof (*req)); 689 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
687 op->h = h; 690 op->h = h;
688 op->res_cb = rcb; 691 op->res_cb = rcb;
689 op->cls = rcb_cls; 692 op->cls = rcb_cls;
@@ -700,7 +703,7 @@ GNUNET_PSYCSTORE_membership_store (struct GNUNET_PSYCSTORE_Handle *h,
700 req->group_generation = GNUNET_htonll (group_generation); 703 req->group_generation = GNUNET_htonll (group_generation);
701 704
702 op->op_id = get_next_op_id (h); 705 op->op_id = get_next_op_id (h);
703 req->op_id = htonl (op->op_id); 706 req->op_id = GNUNET_htonll (op->op_id);
704 707
705 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 708 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
706 transmit_next (h); 709 transmit_next (h);
@@ -746,8 +749,8 @@ GNUNET_PSYCSTORE_membership_test (struct GNUNET_PSYCSTORE_Handle *h,
746 void *rcb_cls) 749 void *rcb_cls)
747{ 750{
748 struct MembershipTestRequest *req; 751 struct MembershipTestRequest *req;
749 struct GNUNET_PSYCSTORE_OperationHandle *op 752 struct GNUNET_PSYCSTORE_OperationHandle *
750 = GNUNET_malloc (sizeof (*op) + sizeof (*req)); 753 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
751 op->h = h; 754 op->h = h;
752 op->res_cb = rcb; 755 op->res_cb = rcb;
753 op->cls = rcb_cls; 756 op->cls = rcb_cls;
@@ -762,7 +765,7 @@ GNUNET_PSYCSTORE_membership_test (struct GNUNET_PSYCSTORE_Handle *h,
762 req->group_generation = GNUNET_htonll (group_generation); 765 req->group_generation = GNUNET_htonll (group_generation);
763 766
764 op->op_id = get_next_op_id (h); 767 op->op_id = get_next_op_id (h);
765 req->op_id = htonl (op->op_id); 768 req->op_id = GNUNET_htonll (op->op_id);
766 769
767 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 770 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
768 transmit_next (h); 771 transmit_next (h);
@@ -794,8 +797,8 @@ GNUNET_PSYCSTORE_fragment_store (struct GNUNET_PSYCSTORE_Handle *h,
794{ 797{
795 uint16_t size = ntohs (msg->header.size); 798 uint16_t size = ntohs (msg->header.size);
796 struct FragmentStoreRequest *req; 799 struct FragmentStoreRequest *req;
797 struct GNUNET_PSYCSTORE_OperationHandle *op 800 struct GNUNET_PSYCSTORE_OperationHandle *
798 = GNUNET_malloc (sizeof (*op) + sizeof (*req) + size); 801 op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + size);
799 op->h = h; 802 op->h = h;
800 op->res_cb = rcb; 803 op->res_cb = rcb;
801 op->cls = rcb_cls; 804 op->cls = rcb_cls;
@@ -809,7 +812,7 @@ GNUNET_PSYCSTORE_fragment_store (struct GNUNET_PSYCSTORE_Handle *h,
809 memcpy (&req[1], msg, size); 812 memcpy (&req[1], msg, size);
810 813
811 op->op_id = get_next_op_id (h); 814 op->op_id = get_next_op_id (h);
812 req->op_id = htonl (op->op_id); 815 req->op_id = GNUNET_htonll (op->op_id);
813 816
814 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 817 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
815 transmit_next (h); 818 transmit_next (h);
@@ -819,7 +822,7 @@ GNUNET_PSYCSTORE_fragment_store (struct GNUNET_PSYCSTORE_Handle *h,
819 822
820 823
821/** 824/**
822 * Retrieve a message fragment by fragment ID. 825 * Retrieve message fragments by fragment ID range.
823 * 826 *
824 * @param h 827 * @param h
825 * Handle for the PSYCstore. 828 * Handle for the PSYCstore.
@@ -829,9 +832,15 @@ GNUNET_PSYCSTORE_fragment_store (struct GNUNET_PSYCSTORE_Handle *h,
829 * The slave requesting the fragment. If not NULL, a membership test is 832 * The slave requesting the fragment. If not NULL, a membership test is
830 * performed first and the fragment is only returned if the slave has 833 * performed first and the fragment is only returned if the slave has
831 * access to it. 834 * access to it.
832 * @param fragment_id 835 * @param first_fragment_id
833 * Fragment ID to retrieve. Use 0 to get the latest message fragment. 836 * First fragment ID to retrieve.
834 * @param fcb 837 * Use 0 to get the latest message fragment.
838 * @param last_fragment_id
839 * Last consecutive fragment ID to retrieve.
840 * Use 0 to get the latest message fragment.
841 * @param fragment_limit
842 * Maximum number of fragments to retrieve.
843 * @param fragment_cb
835 * Callback to call with the retrieved fragments. 844 * Callback to call with the retrieved fragments.
836 * @param rcb 845 * @param rcb
837 * Callback to call with the result of the operation. 846 * Callback to call with the result of the operation.
@@ -844,16 +853,85 @@ struct GNUNET_PSYCSTORE_OperationHandle *
844GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h, 853GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h,
845 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, 854 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
846 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, 855 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
847 uint64_t fragment_id, 856 uint64_t first_fragment_id,
848 GNUNET_PSYCSTORE_FragmentCallback fcb, 857 uint64_t last_fragment_id,
858 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
849 GNUNET_PSYCSTORE_ResultCallback rcb, 859 GNUNET_PSYCSTORE_ResultCallback rcb,
850 void *cls) 860 void *cls)
851{ 861{
852 struct FragmentGetRequest *req; 862 struct FragmentGetRequest *req;
853 struct GNUNET_PSYCSTORE_OperationHandle *op 863 struct GNUNET_PSYCSTORE_OperationHandle *
854 = GNUNET_malloc (sizeof (*op) + sizeof (*req)); 864 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
865 op->h = h;
866 op->data_cb = (DataCallback) fragment_cb;
867 op->res_cb = rcb;
868 op->cls = cls;
869
870 req = (struct FragmentGetRequest *) &op[1];
871 op->msg = (struct GNUNET_MessageHeader *) req;
872 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET);
873 req->header.size = htons (sizeof (*req));
874 req->channel_key = *channel_key;
875 req->first_fragment_id = GNUNET_htonll (first_fragment_id);
876 req->last_fragment_id = GNUNET_htonll (last_fragment_id);
877 if (NULL != slave_key)
878 {
879 req->slave_key = *slave_key;
880 req->do_membership_test = GNUNET_YES;
881 }
882
883 op->op_id = get_next_op_id (h);
884 req->op_id = GNUNET_htonll (op->op_id);
885
886 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
887 transmit_next (h);
888
889 return op;
890}
891
892
893/**
894 * Retrieve latest message fragments.
895 *
896 * @param h
897 * Handle for the PSYCstore.
898 * @param channel_key
899 * The channel we are interested in.
900 * @param slave_key
901 * The slave requesting the fragment. If not NULL, a membership test is
902 * performed first and the fragment is only returned if the slave has
903 * access to it.
904 * @param first_fragment_id
905 * First fragment ID to retrieve.
906 * Use 0 to get the latest message fragment.
907 * @param last_fragment_id
908 * Last consecutive fragment ID to retrieve.
909 * Use 0 to get the latest message fragment.
910 * @param fragment_limit
911 * Maximum number of fragments to retrieve.
912 * @param fragment_cb
913 * Callback to call with the retrieved fragments.
914 * @param rcb
915 * Callback to call with the result of the operation.
916 * @param cls
917 * Closure for the callbacks.
918 *
919 * @return Handle that can be used to cancel the operation.
920 */
921struct GNUNET_PSYCSTORE_OperationHandle *
922GNUNET_PSYCSTORE_fragment_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
923 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
924 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
925 uint64_t fragment_limit,
926 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
927 GNUNET_PSYCSTORE_ResultCallback rcb,
928 void *cls)
929{
930 struct FragmentGetRequest *req;
931 struct GNUNET_PSYCSTORE_OperationHandle *
932 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
855 op->h = h; 933 op->h = h;
856 op->data_cb = (DataCallback) fcb; 934 op->data_cb = (DataCallback) fragment_cb;
857 op->res_cb = rcb; 935 op->res_cb = rcb;
858 op->cls = cls; 936 op->cls = cls;
859 937
@@ -862,7 +940,7 @@ GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h,
862 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET); 940 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET);
863 req->header.size = htons (sizeof (*req)); 941 req->header.size = htons (sizeof (*req));
864 req->channel_key = *channel_key; 942 req->channel_key = *channel_key;
865 req->fragment_id = GNUNET_htonll (fragment_id); 943 req->fragment_limit = GNUNET_ntohll (fragment_limit);
866 if (NULL != slave_key) 944 if (NULL != slave_key)
867 { 945 {
868 req->slave_key = *slave_key; 946 req->slave_key = *slave_key;
@@ -870,7 +948,7 @@ GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h,
870 } 948 }
871 949
872 op->op_id = get_next_op_id (h); 950 op->op_id = get_next_op_id (h);
873 req->op_id = htonl (op->op_id); 951 req->op_id = GNUNET_htonll (op->op_id);
874 952
875 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 953 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
876 transmit_next (h); 954 transmit_next (h);
@@ -880,7 +958,7 @@ GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h,
880 958
881 959
882/** 960/**
883 * Retrieve all fragments of a message. 961 * Retrieve all fragments of messages in a message ID range.
884 * 962 *
885 * @param h 963 * @param h
886 * Handle for the PSYCstore. 964 * Handle for the PSYCstore.
@@ -890,9 +968,13 @@ GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h,
890 * The slave requesting the message. If not NULL, a membership test is 968 * The slave requesting the message. If not NULL, a membership test is
891 * performed first and the message is only returned if the slave has 969 * performed first and the message is only returned if the slave has
892 * access to it. 970 * access to it.
893 * @param message_id 971 * @param first_message_id
894 * Message ID to retrieve. Use 0 to get the latest message. 972 * First message ID to retrieve.
895 * @param fcb 973 * Use 0 to get the latest message.
974 * @param last_message_id
975 * Last consecutive message ID to retrieve.
976 * Use 0 to get the latest message.
977 * @param fragment_cb
896 * Callback to call with the retrieved fragments. 978 * Callback to call with the retrieved fragments.
897 * @param rcb 979 * @param rcb
898 * Callback to call with the result of the operation. 980 * Callback to call with the result of the operation.
@@ -905,16 +987,17 @@ struct GNUNET_PSYCSTORE_OperationHandle *
905GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h, 987GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
906 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, 988 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
907 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, 989 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
908 uint64_t message_id, 990 uint64_t first_message_id,
909 GNUNET_PSYCSTORE_FragmentCallback fcb, 991 uint64_t last_message_id,
992 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
910 GNUNET_PSYCSTORE_ResultCallback rcb, 993 GNUNET_PSYCSTORE_ResultCallback rcb,
911 void *cls) 994 void *cls)
912{ 995{
913 struct MessageGetRequest *req; 996 struct MessageGetRequest *req;
914 struct GNUNET_PSYCSTORE_OperationHandle *op 997 struct GNUNET_PSYCSTORE_OperationHandle *
915 = GNUNET_malloc (sizeof (*op) + sizeof (*req)); 998 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
916 op->h = h; 999 op->h = h;
917 op->data_cb = (DataCallback) fcb; 1000 op->data_cb = (DataCallback) fragment_cb;
918 op->res_cb = rcb; 1001 op->res_cb = rcb;
919 op->cls = cls; 1002 op->cls = cls;
920 1003
@@ -923,7 +1006,8 @@ GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
923 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET); 1006 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET);
924 req->header.size = htons (sizeof (*req)); 1007 req->header.size = htons (sizeof (*req));
925 req->channel_key = *channel_key; 1008 req->channel_key = *channel_key;
926 req->message_id = GNUNET_htonll (message_id); 1009 req->first_message_id = GNUNET_htonll (first_message_id);
1010 req->last_message_id = GNUNET_htonll (last_message_id);
927 if (NULL != slave_key) 1011 if (NULL != slave_key)
928 { 1012 {
929 req->slave_key = *slave_key; 1013 req->slave_key = *slave_key;
@@ -931,7 +1015,68 @@ GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
931 } 1015 }
932 1016
933 op->op_id = get_next_op_id (h); 1017 op->op_id = get_next_op_id (h);
934 req->op_id = htonl (op->op_id); 1018 req->op_id = GNUNET_htonll (op->op_id);
1019
1020 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
1021 transmit_next (h);
1022
1023 return op;
1024}
1025
1026
1027/**
1028 * Retrieve all fragments of the latest messages.
1029 *
1030 * @param h
1031 * Handle for the PSYCstore.
1032 * @param channel_key
1033 * The channel we are interested in.
1034 * @param slave_key
1035 * The slave requesting the message. If not NULL, a membership test is
1036 * performed first and the message is only returned if the slave has
1037 * access to it.
1038 * @param message_limit
1039 * Maximum number of messages to retrieve.
1040 * @param fragment_cb
1041 * Callback to call with the retrieved fragments.
1042 * @param rcb
1043 * Callback to call with the result of the operation.
1044 * @param cls
1045 * Closure for the callbacks.
1046 *
1047 * @return Handle that can be used to cancel the operation.
1048 */
1049struct GNUNET_PSYCSTORE_OperationHandle *
1050GNUNET_PSYCSTORE_message_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
1051 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1052 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
1053 uint64_t message_limit,
1054 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
1055 GNUNET_PSYCSTORE_ResultCallback rcb,
1056 void *cls)
1057{
1058 struct MessageGetRequest *req;
1059 struct GNUNET_PSYCSTORE_OperationHandle *
1060 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
1061 op->h = h;
1062 op->data_cb = (DataCallback) fragment_cb;
1063 op->res_cb = rcb;
1064 op->cls = cls;
1065
1066 req = (struct MessageGetRequest *) &op[1];
1067 op->msg = (struct GNUNET_MessageHeader *) req;
1068 req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET);
1069 req->header.size = htons (sizeof (*req));
1070 req->channel_key = *channel_key;
1071 req->message_limit = GNUNET_ntohll (message_limit);
1072 if (NULL != slave_key)
1073 {
1074 req->slave_key = *slave_key;
1075 req->do_membership_test = GNUNET_YES;
1076 }
1077
1078 op->op_id = get_next_op_id (h);
1079 req->op_id = GNUNET_htonll (op->op_id);
935 1080
936 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 1081 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
937 transmit_next (h); 1082 transmit_next (h);
@@ -956,9 +1101,9 @@ GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
956 * Message ID to retrieve. Use 0 to get the latest message. 1101 * Message ID to retrieve. Use 0 to get the latest message.
957 * @param fragment_offset 1102 * @param fragment_offset
958 * Offset of the fragment to retrieve. 1103 * Offset of the fragment to retrieve.
959 * @param fcb 1104 * @param fragment_cb
960 * Callback to call with the retrieved fragments. 1105 * Callback to call with the retrieved fragments.
961 * @param rcb 1106 * @param result_cb
962 * Callback to call with the result of the operation. 1107 * Callback to call with the result of the operation.
963 * @param cls 1108 * @param cls
964 * Closure for the callbacks. 1109 * Closure for the callbacks.
@@ -971,15 +1116,15 @@ GNUNET_PSYCSTORE_message_get_fragment (struct GNUNET_PSYCSTORE_Handle *h,
971 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, 1116 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
972 uint64_t message_id, 1117 uint64_t message_id,
973 uint64_t fragment_offset, 1118 uint64_t fragment_offset,
974 GNUNET_PSYCSTORE_FragmentCallback fcb, 1119 GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
975 GNUNET_PSYCSTORE_ResultCallback rcb, 1120 GNUNET_PSYCSTORE_ResultCallback rcb,
976 void *cls) 1121 void *cls)
977{ 1122{
978 struct MessageGetFragmentRequest *req; 1123 struct MessageGetFragmentRequest *req;
979 struct GNUNET_PSYCSTORE_OperationHandle *op 1124 struct GNUNET_PSYCSTORE_OperationHandle *
980 = GNUNET_malloc (sizeof (*op) + sizeof (*req)); 1125 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
981 op->h = h; 1126 op->h = h;
982 op->data_cb = (DataCallback) fcb; 1127 op->data_cb = (DataCallback) fragment_cb;
983 op->res_cb = rcb; 1128 op->res_cb = rcb;
984 op->cls = cls; 1129 op->cls = cls;
985 1130
@@ -997,7 +1142,7 @@ GNUNET_PSYCSTORE_message_get_fragment (struct GNUNET_PSYCSTORE_Handle *h,
997 } 1142 }
998 1143
999 op->op_id = get_next_op_id (h); 1144 op->op_id = get_next_op_id (h);
1000 req->op_id = htonl (op->op_id); 1145 req->op_id = GNUNET_htonll (op->op_id);
1001 1146
1002 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 1147 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
1003 transmit_next (h); 1148 transmit_next (h);
@@ -1026,8 +1171,8 @@ GNUNET_PSYCSTORE_counters_get (struct GNUNET_PSYCSTORE_Handle *h,
1026 void *ccb_cls) 1171 void *ccb_cls)
1027{ 1172{
1028 struct OperationRequest *req; 1173 struct OperationRequest *req;
1029 struct GNUNET_PSYCSTORE_OperationHandle *op 1174 struct GNUNET_PSYCSTORE_OperationHandle *
1030 = GNUNET_malloc (sizeof (*op) + sizeof (*req)); 1175 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
1031 op->h = h; 1176 op->h = h;
1032 op->data_cb = ccb; 1177 op->data_cb = ccb;
1033 op->cls = ccb_cls; 1178 op->cls = ccb_cls;
@@ -1039,7 +1184,7 @@ GNUNET_PSYCSTORE_counters_get (struct GNUNET_PSYCSTORE_Handle *h,
1039 req->channel_key = *channel_key; 1184 req->channel_key = *channel_key;
1040 1185
1041 op->op_id = get_next_op_id (h); 1186 op->op_id = get_next_op_id (h);
1042 req->op_id = htonl (op->op_id); 1187 req->op_id = GNUNET_htonll (op->op_id);
1043 1188
1044 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 1189 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
1045 transmit_next (h); 1190 transmit_next (h);
@@ -1109,7 +1254,7 @@ GNUNET_PSYCSTORE_state_modify (struct GNUNET_PSYCSTORE_Handle *h,
1109 memcpy ((char *) &req[1] + name_size, modifiers[i].value, modifiers[i].value_size); 1254 memcpy ((char *) &req[1] + name_size, modifiers[i].value, modifiers[i].value_size);
1110 1255
1111 op->op_id = get_next_op_id (h); 1256 op->op_id = get_next_op_id (h);
1112 req->op_id = htonl (op->op_id); 1257 req->op_id = GNUNET_htonll (op->op_id);
1113 1258
1114 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 1259 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
1115 transmit_next (h); 1260 transmit_next (h);
@@ -1175,7 +1320,7 @@ GNUNET_PSYCSTORE_state_sync (struct GNUNET_PSYCSTORE_Handle *h,
1175 memcpy ((char *) &req[1] + name_size, modifiers[i].value, modifiers[i].value_size); 1320 memcpy ((char *) &req[1] + name_size, modifiers[i].value, modifiers[i].value_size);
1176 1321
1177 op->op_id = get_next_op_id (h); 1322 op->op_id = get_next_op_id (h);
1178 req->op_id = htonl (op->op_id); 1323 req->op_id = GNUNET_htonll (op->op_id);
1179 1324
1180 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 1325 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
1181 transmit_next (h); 1326 transmit_next (h);
@@ -1204,8 +1349,8 @@ GNUNET_PSYCSTORE_state_reset (struct GNUNET_PSYCSTORE_Handle *h,
1204 void *rcb_cls) 1349 void *rcb_cls)
1205{ 1350{
1206 struct OperationRequest *req; 1351 struct OperationRequest *req;
1207 struct GNUNET_PSYCSTORE_OperationHandle *op 1352 struct GNUNET_PSYCSTORE_OperationHandle *
1208 = GNUNET_malloc (sizeof (*op) + sizeof (*req)); 1353 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
1209 op->h = h; 1354 op->h = h;
1210 op->res_cb = rcb; 1355 op->res_cb = rcb;
1211 op->cls = rcb_cls; 1356 op->cls = rcb_cls;
@@ -1217,7 +1362,7 @@ GNUNET_PSYCSTORE_state_reset (struct GNUNET_PSYCSTORE_Handle *h,
1217 req->channel_key = *channel_key; 1362 req->channel_key = *channel_key;
1218 1363
1219 op->op_id = get_next_op_id (h); 1364 op->op_id = get_next_op_id (h);
1220 req->op_id = htonl (op->op_id); 1365 req->op_id = GNUNET_htonll (op->op_id);
1221 1366
1222 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 1367 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
1223 transmit_next (h); 1368 transmit_next (h);
@@ -1247,8 +1392,8 @@ GNUNET_PSYCSTORE_state_hash_update (struct GNUNET_PSYCSTORE_Handle *h,
1247 void *rcb_cls) 1392 void *rcb_cls)
1248{ 1393{
1249 struct StateHashUpdateRequest *req; 1394 struct StateHashUpdateRequest *req;
1250 struct GNUNET_PSYCSTORE_OperationHandle *op 1395 struct GNUNET_PSYCSTORE_OperationHandle *
1251 = GNUNET_malloc (sizeof (*op) + sizeof (*req)); 1396 op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
1252 op->h = h; 1397 op->h = h;
1253 op->res_cb = rcb; 1398 op->res_cb = rcb;
1254 op->cls = rcb_cls; 1399 op->cls = rcb_cls;
@@ -1261,7 +1406,7 @@ GNUNET_PSYCSTORE_state_hash_update (struct GNUNET_PSYCSTORE_Handle *h,
1261 req->hash = *hash; 1406 req->hash = *hash;
1262 1407
1263 op->op_id = get_next_op_id (h); 1408 op->op_id = get_next_op_id (h);
1264 req->op_id = htonl (op->op_id); 1409 req->op_id = GNUNET_htonll (op->op_id);
1265 1410
1266 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 1411 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
1267 transmit_next (h); 1412 transmit_next (h);
@@ -1292,8 +1437,8 @@ GNUNET_PSYCSTORE_state_get (struct GNUNET_PSYCSTORE_Handle *h,
1292{ 1437{
1293 size_t name_size = strlen (name) + 1; 1438 size_t name_size = strlen (name) + 1;
1294 struct OperationRequest *req; 1439 struct OperationRequest *req;
1295 struct GNUNET_PSYCSTORE_OperationHandle *op 1440 struct GNUNET_PSYCSTORE_OperationHandle *
1296 = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size); 1441 op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size);
1297 op->h = h; 1442 op->h = h;
1298 op->data_cb = (DataCallback) scb; 1443 op->data_cb = (DataCallback) scb;
1299 op->res_cb = rcb; 1444 op->res_cb = rcb;
@@ -1307,7 +1452,7 @@ GNUNET_PSYCSTORE_state_get (struct GNUNET_PSYCSTORE_Handle *h,
1307 memcpy (&req[1], name, name_size); 1452 memcpy (&req[1], name, name_size);
1308 1453
1309 op->op_id = get_next_op_id (h); 1454 op->op_id = get_next_op_id (h);
1310 req->op_id = htonl (op->op_id); 1455 req->op_id = GNUNET_htonll (op->op_id);
1311 1456
1312 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 1457 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
1313 transmit_next (h); 1458 transmit_next (h);
@@ -1339,8 +1484,8 @@ GNUNET_PSYCSTORE_state_get_prefix (struct GNUNET_PSYCSTORE_Handle *h,
1339{ 1484{
1340 size_t name_size = strlen (name_prefix) + 1; 1485 size_t name_size = strlen (name_prefix) + 1;
1341 struct OperationRequest *req; 1486 struct OperationRequest *req;
1342 struct GNUNET_PSYCSTORE_OperationHandle *op 1487 struct GNUNET_PSYCSTORE_OperationHandle *
1343 = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size); 1488 op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size);
1344 op->h = h; 1489 op->h = h;
1345 op->data_cb = (DataCallback) scb; 1490 op->data_cb = (DataCallback) scb;
1346 op->res_cb = rcb; 1491 op->res_cb = rcb;
@@ -1354,7 +1499,7 @@ GNUNET_PSYCSTORE_state_get_prefix (struct GNUNET_PSYCSTORE_Handle *h,
1354 memcpy (&req[1], name_prefix, name_size); 1499 memcpy (&req[1], name_prefix, name_size);
1355 1500
1356 op->op_id = get_next_op_id (h); 1501 op->op_id = get_next_op_id (h);
1357 req->op_id = htonl (op->op_id); 1502 req->op_id = GNUNET_htonll (op->op_id);
1358 1503
1359 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); 1504 GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
1360 transmit_next (h); 1505 transmit_next (h);
diff --git a/src/psycstore/test_plugin_psycstore.c b/src/psycstore/test_plugin_psycstore.c
index 8267ddba8..a6c456fec 100644
--- a/src/psycstore/test_plugin_psycstore.c
+++ b/src/psycstore/test_plugin_psycstore.c
@@ -204,11 +204,17 @@ run (void *cls, char *const *args, const char *cfgfile,
204 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE); 204 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
205 msg->header.size = htons (sizeof (*msg) + sizeof (channel_pub_key)); 205 msg->header.size = htons (sizeof (*msg) + sizeof (channel_pub_key));
206 206
207 uint64_t fragment_id = INT64_MAX - 1;
208 msg->fragment_id = GNUNET_htonll (fragment_id);
209
210 uint64_t message_id = INT64_MAX - 10;
211 msg->message_id = GNUNET_htonll (message_id);
212
213 uint64_t group_generation = INT64_MAX - 3;
214 msg->group_generation = GNUNET_htonll (group_generation);
215
207 msg->hop_counter = htonl (9); 216 msg->hop_counter = htonl (9);
208 msg->fragment_id = GNUNET_htonll (INT64_MAX - 1);
209 msg->fragment_offset = GNUNET_htonll (0); 217 msg->fragment_offset = GNUNET_htonll (0);
210 msg->message_id = GNUNET_htonll (INT64_MAX - 10);
211 msg->group_generation = GNUNET_htonll (INT64_MAX - 3);
212 msg->flags = htonl (GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT); 218 msg->flags = htonl (GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT);
213 219
214 memcpy (&msg[1], &channel_pub_key, sizeof (channel_pub_key)); 220 memcpy (&msg[1], &channel_pub_key, sizeof (channel_pub_key));
@@ -225,14 +231,19 @@ run (void *cls, char *const *args, const char *cfgfile,
225 fcls.msg[0] = msg; 231 fcls.msg[0] = msg;
226 fcls.flags[0] = GNUNET_PSYCSTORE_MESSAGE_STATE; 232 fcls.flags[0] = GNUNET_PSYCSTORE_MESSAGE_STATE;
227 233
228 GNUNET_assert (GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg, 234 GNUNET_assert (
229 fcls.flags[0])); 235 GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg,
236 fcls.flags[0]));
230 237
231 GNUNET_assert (GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key, 238 uint64_t ret_frags = 0;
232 GNUNET_ntohll (msg->fragment_id), 239 GNUNET_assert (
233 fragment_cb, &fcls)); 240 GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key,
241 fragment_id, fragment_id,
242 &ret_frags, fragment_cb, &fcls));
234 GNUNET_assert (fcls.n == 1); 243 GNUNET_assert (fcls.n == 1);
235 244
245 // FIXME: test fragment_get_latest and message_get_latest
246
236 fcls.n = 0; 247 fcls.n = 0;
237 248
238 GNUNET_assert ( 249 GNUNET_assert (
@@ -250,9 +261,10 @@ run (void *cls, char *const *args, const char *cfgfile,
250 fcls.n = 0; 261 fcls.n = 0;
251 fcls.flags[0] |= GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED; 262 fcls.flags[0] |= GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED;
252 263
253 GNUNET_assert (GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key, 264 GNUNET_assert (
254 GNUNET_ntohll (msg->fragment_id), 265 GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key,
255 fragment_cb, &fcls)); 266 fragment_id, fragment_id,
267 &ret_frags, fragment_cb, &fcls));
256 GNUNET_assert (fcls.n == 1); 268 GNUNET_assert (fcls.n == 1);
257 269
258 struct GNUNET_MULTICAST_MessageHeader *msg1 270 struct GNUNET_MULTICAST_MessageHeader *msg1
@@ -270,15 +282,17 @@ run (void *cls, char *const *args, const char *cfgfile,
270 GNUNET_assert (GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg1, 282 GNUNET_assert (GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg1,
271 fcls.flags[1])); 283 fcls.flags[1]));
272 284
273 uint64_t retfrags = 0; 285 GNUNET_assert (
274 GNUNET_assert (GNUNET_OK == db->message_get (db->cls, &channel_pub_key, 286 GNUNET_OK == db->message_get (db->cls, &channel_pub_key,
275 GNUNET_ntohll (msg->message_id), 287 message_id, message_id,
276 &retfrags, fragment_cb, &fcls)); 288 &ret_frags, fragment_cb, &fcls));
277 GNUNET_assert (fcls.n == 2 && retfrags == 2); 289 GNUNET_assert (fcls.n == 2 && ret_frags == 2);
278 290
279 /* Message counters */ 291 /* Message counters */
280 292
281 uint64_t fragment_id = 0, message_id = 0, group_generation = 0; 293 fragment_id = 0;
294 message_id = 0;
295 group_generation = 0;
282 GNUNET_assert ( 296 GNUNET_assert (
283 GNUNET_OK == db->counters_message_get (db->cls, &channel_pub_key, 297 GNUNET_OK == db->counters_message_get (db->cls, &channel_pub_key,
284 &fragment_id, &message_id, 298 &fragment_id, &message_id,
diff --git a/src/psycstore/test_psycstore.c b/src/psycstore/test_psycstore.c
index 3ef2439e3..125e64f58 100644
--- a/src/psycstore/test_psycstore.c
+++ b/src/psycstore/test_psycstore.c
@@ -25,6 +25,8 @@
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 */ 26 */
27 27
28#include <inttypes.h>
29
28#include "platform.h" 30#include "platform.h"
29#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
30#include "gnunet_common.h" 32#include "gnunet_common.h"
@@ -302,19 +304,22 @@ fragment_result (void *cls,
302 enum GNUNET_PSYCSTORE_MessageFlags flags) 304 enum GNUNET_PSYCSTORE_MessageFlags flags)
303{ 305{
304 struct FragmentClosure *fcls = cls; 306 struct FragmentClosure *fcls = cls;
307 GNUNET_assert (fcls->n < fcls->n_expected);
305 struct GNUNET_MULTICAST_MessageHeader *msg0 = fcls->msg[fcls->n]; 308 struct GNUNET_MULTICAST_MessageHeader *msg0 = fcls->msg[fcls->n];
306 uint64_t flags0 = fcls->flags[fcls->n++]; 309 uint64_t flags0 = fcls->flags[fcls->n++];
307 310
308 if (flags == flags0 && msg->header.size == msg0->header.size 311 if (flags == flags0 && msg->header.size == msg0->header.size
309 && 0 == memcmp (msg, msg0, ntohs (msg->header.size))) 312 && 0 == memcmp (msg, msg0, ntohs (msg->header.size)))
310 { 313 {
311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " fragment %llu matches\n", 314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " fragment %" PRIu64 " matches\n",
312 GNUNET_ntohll (msg->fragment_id)); 315 GNUNET_ntohll (msg->fragment_id));
313 return GNUNET_YES; 316 return GNUNET_YES;
314 } 317 }
315 else 318 else
316 { 319 {
317 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " fragment %llu differs\n", 320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
321 " fragment differs: expected %" PRIu64 ", got %" PRIu64 "\n",
322 GNUNET_ntohll (msg0->fragment_id),
318 GNUNET_ntohll (msg->fragment_id)); 323 GNUNET_ntohll (msg->fragment_id));
319 GNUNET_assert (0); 324 GNUNET_assert (0);
320 return GNUNET_SYSERR; 325 return GNUNET_SYSERR;
@@ -323,13 +328,12 @@ fragment_result (void *cls,
323 328
324 329
325void 330void
326message_get_result (void *cls, int64_t result, const char *err_msg) 331message_get_latest_result (void *cls, int64_t result, const char *err_msg)
327{ 332{
328 struct FragmentClosure *fcls = cls; 333 struct FragmentClosure *fcls = cls;
329 op = NULL; 334 op = NULL;
330 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get:\t%d\n", result); 335 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_latest:\t%d\n", result);
331 GNUNET_assert (result > 0 && fcls->n && fcls->n_expected); 336 GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
332
333 337
334 modifiers[0] = (struct GNUNET_ENV_Modifier) { 338 modifiers[0] = (struct GNUNET_ENV_Modifier) {
335 .oper = '=', 339 .oper = '=',
@@ -351,29 +355,46 @@ message_get_result (void *cls, int64_t result, const char *err_msg)
351 355
352 356
353void 357void
358message_get_result (void *cls, int64_t result, const char *err_msg)
359{
360 struct FragmentClosure *fcls = cls;
361 op = NULL;
362 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get:\t%d\n", result);
363 GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
364
365 fcls->n = 0;
366 fcls->n_expected = 3;
367 op = GNUNET_PSYCSTORE_message_get_latest (h, &channel_pub_key, &slave_pub_key,
368 1, &fragment_result,
369 &message_get_latest_result, fcls);
370}
371
372
373void
354message_get_fragment_result (void *cls, int64_t result, const char *err_msg) 374message_get_fragment_result (void *cls, int64_t result, const char *err_msg)
355{ 375{
356 struct FragmentClosure *fcls = cls; 376 struct FragmentClosure *fcls = cls;
357 op = NULL; 377 op = NULL;
358 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_fragment:\t%d\n", result); 378 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_fragment:\t%d\n", result);
359 GNUNET_assert (result > 0 && fcls->n && fcls->n_expected); 379 GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
360 380
361 fcls->n = 0; 381 fcls->n = 0;
362 fcls->n_expected = 3; 382 fcls->n_expected = 3;
383 uint64_t message_id = GNUNET_ntohll (fcls->msg[0]->message_id);
363 op = GNUNET_PSYCSTORE_message_get (h, &channel_pub_key, &slave_pub_key, 384 op = GNUNET_PSYCSTORE_message_get (h, &channel_pub_key, &slave_pub_key,
364 GNUNET_ntohll (fcls->msg[0]->message_id), 385 message_id, message_id,
365 &fragment_result, 386 &fragment_result,
366 &message_get_result, fcls); 387 &message_get_result, fcls);
367} 388}
368 389
369 390
370void 391void
371fragment_get_result (void *cls, int64_t result, const char *err_msg) 392fragment_get_latest_result (void *cls, int64_t result, const char *err_msg)
372{ 393{
373 struct FragmentClosure *fcls = cls; 394 struct FragmentClosure *fcls = cls;
374 op = NULL; 395 op = NULL;
375 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_get:\t%d\n", result); 396 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_get_latest:\t%d\n", result);
376 GNUNET_assert (result > 0 && fcls->n && fcls->n_expected); 397 GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
377 398
378 fcls->n = 1; 399 fcls->n = 1;
379 fcls->n_expected = 2; 400 fcls->n_expected = 2;
@@ -381,9 +402,24 @@ fragment_get_result (void *cls, int64_t result, const char *err_msg)
381 GNUNET_ntohll (fcls->msg[1]->message_id), 402 GNUNET_ntohll (fcls->msg[1]->message_id),
382 GNUNET_ntohll (fcls->msg[1]->fragment_offset), 403 GNUNET_ntohll (fcls->msg[1]->fragment_offset),
383 &fragment_result, 404 &fragment_result,
384 &message_get_fragment_result, 405 &message_get_fragment_result, fcls);
385 fcls); 406}
407
386 408
409void
410fragment_get_result (void *cls, int64_t result, const char *err_msg)
411{
412 struct FragmentClosure *fcls = cls;
413 op = NULL;
414 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_get:\t%d\n", result);
415 GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
416
417 fcls->n = 0;
418 fcls->n_expected = 3;
419 op = GNUNET_PSYCSTORE_fragment_get_latest (h, &channel_pub_key,
420 &slave_pub_key, fcls->n_expected,
421 &fragment_result,
422 &fragment_get_latest_result, fcls);
387} 423}
388 424
389 425
@@ -398,8 +434,9 @@ fragment_store_result (void *cls, int64_t result, const char *err_msg)
398 { /* last fragment */ 434 { /* last fragment */
399 fcls.n = 0; 435 fcls.n = 0;
400 fcls.n_expected = 1; 436 fcls.n_expected = 1;
437 uint64_t fragment_id = GNUNET_ntohll (fcls.msg[0]->fragment_id);
401 op = GNUNET_PSYCSTORE_fragment_get (h, &channel_pub_key, &slave_pub_key, 438 op = GNUNET_PSYCSTORE_fragment_get (h, &channel_pub_key, &slave_pub_key,
402 GNUNET_ntohll (fcls.msg[0]->fragment_id), 439 fragment_id, fragment_id,
403 &fragment_result, 440 &fragment_result,
404 &fragment_get_result, &fcls); 441 &fragment_get_result, &fcls);
405 } 442 }
diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c
index c75589811..d297a153b 100644
--- a/src/social/gnunet-service-social.c
+++ b/src/social/gnunet-service-social.c
@@ -467,17 +467,17 @@ client_send_msg (const struct Place *plc,
467 * Called after a PSYC master is started. 467 * Called after a PSYC master is started.
468 */ 468 */
469static void 469static void
470psyc_master_started (void *cls, uint64_t max_message_id) 470psyc_master_started (void *cls, int result, uint64_t max_message_id)
471{ 471{
472 struct Host *hst = cls; 472 struct Host *hst = cls;
473 struct Place *plc = &hst->plc; 473 struct Place *plc = &hst->plc;
474 plc->max_message_id = max_message_id; 474 plc->max_message_id = max_message_id;
475 plc->is_ready = GNUNET_YES; 475 plc->is_ready = GNUNET_YES;
476 476
477 struct CountersResult res; 477 struct GNUNET_PSYC_CountersResultMessage res;
478 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK); 478 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
479 res.header.size = htons (sizeof (res)); 479 res.header.size = htons (sizeof (res));
480 res.result_code = htonl (GNUNET_OK); 480 res.result_code = htonl (result - INT32_MIN);
481 res.max_message_id = GNUNET_htonll (plc->max_message_id); 481 res.max_message_id = GNUNET_htonll (plc->max_message_id);
482 482
483 client_send_msg (plc, &res.header); 483 client_send_msg (plc, &res.header);
@@ -507,17 +507,17 @@ psyc_recv_join_request (void *cls,
507 * Called after a PSYC slave is connected. 507 * Called after a PSYC slave is connected.
508 */ 508 */
509static void 509static void
510psyc_slave_connected (void *cls, uint64_t max_message_id) 510psyc_slave_connected (void *cls, int result, uint64_t max_message_id)
511{ 511{
512 struct Guest *gst = cls; 512 struct Guest *gst = cls;
513 struct Place *plc = &gst->plc; 513 struct Place *plc = &gst->plc;
514 plc->max_message_id = max_message_id; 514 plc->max_message_id = max_message_id;
515 plc->is_ready = GNUNET_YES; 515 plc->is_ready = GNUNET_YES;
516 516
517 struct CountersResult res; 517 struct GNUNET_PSYC_CountersResultMessage res;
518 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK); 518 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
519 res.header.size = htons (sizeof (res)); 519 res.header.size = htons (sizeof (res));
520 res.result_code = htonl (GNUNET_OK); 520 res.result_code = htonl (result - INT32_MIN);
521 res.max_message_id = GNUNET_htonll (plc->max_message_id); 521 res.max_message_id = GNUNET_htonll (plc->max_message_id);
522 522
523 client_send_msg (plc, &res.header); 523 client_send_msg (plc, &res.header);
@@ -608,7 +608,7 @@ client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client,
608 { 608 {
609 plc = &hst->plc; 609 plc = &hst->plc;
610 610
611 struct CountersResult res; 611 struct GNUNET_PSYC_CountersResultMessage res;
612 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK); 612 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
613 res.header.size = htons (sizeof (res)); 613 res.header.size = htons (sizeof (res));
614 res.result_code = htonl (GNUNET_OK); 614 res.result_code = htonl (GNUNET_OK);
@@ -724,7 +724,7 @@ client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client,
724 { 724 {
725 plc = &gst->plc; 725 plc = &gst->plc;
726 726
727 struct CountersResult res; 727 struct GNUNET_PSYC_CountersResultMessage res;
728 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK); 728 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
729 res.header.size = htons (sizeof (res)); 729 res.header.size = htons (sizeof (res));
730 res.result_code = htonl (GNUNET_OK); 730 res.result_code = htonl (GNUNET_OK);
diff --git a/src/social/social.h b/src/social/social.h
index 00edaefd1..5de1e5e80 100644
--- a/src/social/social.h
+++ b/src/social/social.h
@@ -88,25 +88,6 @@ struct GuestEnterRequest
88/**** service -> library ****/ 88/**** service -> library ****/
89 89
90 90
91struct CountersResult
92{
93 /**
94 * Type: GNUNET_MESSAGE_TYPE_PSYC_RESULT_COUNTERS
95 */
96 struct GNUNET_MessageHeader header;
97
98 /**
99 * Status code for the operation.
100 */
101 int32_t result_code GNUNET_PACKED;
102
103 /**
104 * Last message ID sent to the channel.
105 */
106 uint64_t max_message_id;
107};
108
109
110#if REMOVE 91#if REMOVE
111struct NymEnterRequest 92struct NymEnterRequest
112{ 93{
diff --git a/src/social/social_api.c b/src/social/social_api.c
index 76fd0f9f9..dfcf18883 100644
--- a/src/social/social_api.c
+++ b/src/social/social_api.c
@@ -640,8 +640,9 @@ host_recv_enter_ack (void *cls,
640 640
641 struct GNUNET_PSYC_CountersResultMessage * 641 struct GNUNET_PSYC_CountersResultMessage *
642 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg; 642 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
643 int32_t result = ntohl (cres->result_code) + INT32_MIN;
643 if (NULL != hst->enter_cb) 644 if (NULL != hst->enter_cb)
644 hst->enter_cb (hst->cb_cls, GNUNET_ntohll (cres->max_message_id)); 645 hst->enter_cb (hst->cb_cls, result, GNUNET_ntohll (cres->max_message_id));
645} 646}
646 647
647 648
@@ -704,9 +705,9 @@ guest_recv_enter_ack (void *cls,
704 705
705 struct GNUNET_PSYC_CountersResultMessage * 706 struct GNUNET_PSYC_CountersResultMessage *
706 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg; 707 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
708 int32_t result = ntohl (cres->result_code) + INT32_MIN;
707 if (NULL != gst->enter_cb) 709 if (NULL != gst->enter_cb)
708 gst->enter_cb (gst->cb_cls, ntohl (cres->result_code), 710 gst->enter_cb (gst->cb_cls, result, GNUNET_ntohll (cres->max_message_id));
709 GNUNET_ntohll (cres->max_message_id));
710} 711}
711 712
712 713
@@ -734,7 +735,7 @@ static struct GNUNET_CLIENT_MANAGER_MessageHandler host_handlers[] =
734{ 735{
735 { &host_recv_enter_ack, NULL, 736 { &host_recv_enter_ack, NULL,
736 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK, 737 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK,
737 sizeof (struct CountersResult), GNUNET_NO }, 738 sizeof (struct GNUNET_PSYC_CountersResultMessage), GNUNET_NO },
738 739
739 { &host_recv_enter_request, NULL, 740 { &host_recv_enter_request, NULL,
740 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST, 741 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
@@ -758,7 +759,7 @@ static struct GNUNET_CLIENT_MANAGER_MessageHandler guest_handlers[] =
758{ 759{
759 { &guest_recv_enter_ack, NULL, 760 { &guest_recv_enter_ack, NULL,
760 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK, 761 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK,
761 sizeof (struct CountersResult), GNUNET_NO }, 762 sizeof (struct GNUNET_PSYC_CountersResultMessage), GNUNET_NO },
762 763
763 { &host_recv_enter_request, NULL, 764 { &host_recv_enter_request, NULL,
764 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST, 765 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
@@ -1598,18 +1599,22 @@ struct GNUNET_SOCIAL_WatchHandle;
1598/** 1599/**
1599 * Watch a place for changed objects. 1600 * Watch a place for changed objects.
1600 * 1601 *
1601 * @param place Place to watch. 1602 * @param place
1602 * @param object_filter Object prefix to match. 1603 * Place to watch.
1603 * @param state_cb Function to call when an object/state changes. 1604 * @param object_filter
1604 * @param state_cb_cls Closure for callback. 1605 * Object prefix to match.
1606 * @param state_var_cb
1607 * Function to call when an object/state var changes.
1608 * @param cls
1609 * Closure for callback.
1605 * 1610 *
1606 * @return Handle that can be used to cancel watching. 1611 * @return Handle that can be used to cancel watching.
1607 */ 1612 */
1608struct GNUNET_SOCIAL_WatchHandle * 1613struct GNUNET_SOCIAL_WatchHandle *
1609GNUNET_SOCIAL_place_watch (struct GNUNET_SOCIAL_Place *place, 1614GNUNET_SOCIAL_place_watch (struct GNUNET_SOCIAL_Place *place,
1610 const char *object_filter, 1615 const char *object_filter,
1611 GNUNET_PSYC_StateCallback state_cb, 1616 GNUNET_PSYC_StateVarCallback state_var_cb,
1612 void *state_cb_cls) 1617 void *cls)
1613{ 1618{
1614 return NULL; 1619 return NULL;
1615} 1620}
@@ -1633,18 +1638,22 @@ struct GNUNET_SOCIAL_LookHandle;
1633/** 1638/**
1634 * Look at objects in the place with a matching name prefix. 1639 * Look at objects in the place with a matching name prefix.
1635 * 1640 *
1636 * @param place The place to look its objects at. 1641 * @param place
1637 * @param name_prefix Look at objects with names beginning with this value. 1642 * The place to look its objects at.
1638 * @param state_cb Function to call for each object found. 1643 * @param name_prefix
1639 * @param state_cb_cls Closure for callback function. 1644 * Look at objects with names beginning with this value.
1645 * @param state_var_cb
1646 * Function to call for each object found.
1647 * @param cls
1648 * Closure for callback function.
1640 * 1649 *
1641 * @return Handle that can be used to stop looking at objects. 1650 * @return Handle that can be used to stop looking at objects.
1642 */ 1651 */
1643struct GNUNET_SOCIAL_LookHandle * 1652struct GNUNET_SOCIAL_LookHandle *
1644GNUNET_SOCIAL_place_look (struct GNUNET_SOCIAL_Place *place, 1653GNUNET_SOCIAL_place_look (struct GNUNET_SOCIAL_Place *place,
1645 const char *name_prefix, 1654 const char *name_prefix,
1646 GNUNET_PSYC_StateCallback state_cb, 1655 GNUNET_PSYC_StateVarCallback state_var_cb,
1647 void *state_cb_cls) 1656 void *cls)
1648{ 1657{
1649 return NULL; 1658 return NULL;
1650} 1659}