diff options
Diffstat (limited to 'src/psyc/psyc_api.c')
-rw-r--r-- | src/psyc/psyc_api.c | 414 |
1 files changed, 334 insertions, 80 deletions
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 | ||
46 | struct 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 | */ |
168 | struct GNUNET_PSYC_Story | 213 | static uint64_t |
214 | op_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 | */ |
177 | struct GNUNET_PSYC_StateQuery | 225 | static struct OperationListItem * |
226 | op_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 | |
239 | static uint64_t | ||
240 | op_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 | |||
258 | static int | ||
259 | op_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 | ||
183 | static void | 286 | static void |
@@ -203,6 +306,79 @@ channel_recv_disconnect (void *cls, | |||
203 | 306 | ||
204 | 307 | ||
205 | static void | 308 | static void |
309 | channel_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 | |||
335 | static void | ||
336 | channel_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 | |||
381 | static void | ||
206 | channel_recv_message (void *cls, | 382 | channel_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 | |||
808 | GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *chn, | 1014 | GNUNET_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, | |||
845 | void | 1055 | void |
846 | GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *chn, | 1056 | GNUNET_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 | */ |
882 | struct GNUNET_PSYC_Story * | 1095 | void |
883 | GNUNET_PSYC_channel_story_tell (struct GNUNET_PSYC_Channel *channel, | 1096 | GNUNET_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 | */ |
903 | void | 1133 | void |
904 | GNUNET_PSYC_channel_story_tell_cancel (struct GNUNET_PSYC_Story *story) | 1134 | GNUNET_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 | */ |
926 | struct GNUNET_PSYC_StateQuery * | 1171 | void |
927 | GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel, | 1172 | GNUNET_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. |
953 | struct GNUNET_PSYC_StateQuery * | 1206 | * @param result_cb |
954 | GNUNET_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 | */ |
968 | void | 1212 | void |
969 | GNUNET_PSYC_channel_state_get_cancel (struct GNUNET_PSYC_StateQuery *query) | 1213 | GNUNET_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 */ |