diff options
-rw-r--r-- | src/include/gnunet_namestore_service.h | 55 | ||||
-rw-r--r-- | src/namestore/Makefile.am | 11 | ||||
-rw-r--r-- | src/namestore/gnunet-service-namestore.c | 141 | ||||
-rw-r--r-- | src/namestore/namestore.h | 12 | ||||
-rw-r--r-- | src/namestore/namestore_api.c | 108 |
5 files changed, 285 insertions, 42 deletions
diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h index 7db5e9d9e..619b81aed 100644 --- a/src/include/gnunet_namestore_service.h +++ b/src/include/gnunet_namestore_service.h | |||
@@ -212,6 +212,61 @@ GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h, | |||
212 | 212 | ||
213 | 213 | ||
214 | /** | 214 | /** |
215 | * Open a record set for editing. | ||
216 | * Retrieves an exclusive lock on this set. | ||
217 | * Must be commited using @a GNUNET_NAMESTORE_records_commit | ||
218 | * | ||
219 | * @param h handle to the namestore | ||
220 | * @param pkey private key of the zone | ||
221 | * @param label name that is being mapped | ||
222 | * @param error_cb function to call on error (i.e. disconnect or unable to get lock) | ||
223 | * the handle is afterwards invalid | ||
224 | * @param error_cb_cls closure for @a error_cb | ||
225 | * @param rm function to call with the result (with 0 records if we don't have that label) | ||
226 | * @param rm_cls closure for @a rm | ||
227 | * @return handle to abort the request | ||
228 | */ | ||
229 | struct GNUNET_NAMESTORE_QueueEntry * | ||
230 | GNUNET_NAMESTORE_records_open (struct GNUNET_NAMESTORE_Handle *h, | ||
231 | const struct | ||
232 | GNUNET_IDENTITY_PrivateKey *pkey, | ||
233 | const char *label, | ||
234 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
235 | void *error_cb_cls, | ||
236 | GNUNET_NAMESTORE_RecordMonitor rm, | ||
237 | void *rm_cls); | ||
238 | |||
239 | /** | ||
240 | * Commit the record set to the namestore. | ||
241 | * Releases the lock on the record set. | ||
242 | * Use an empty array to | ||
243 | * remove all records under the given name. | ||
244 | * | ||
245 | * The continuation is called after the value has been stored in the | ||
246 | * database. Monitors may be notified asynchronously (basically with | ||
247 | * a buffer). However, if any monitor is consistently too slow to | ||
248 | * keep up with the changes, calling @a cont will be delayed until the | ||
249 | * monitors do keep up. | ||
250 | * | ||
251 | * @param h handle to the namestore | ||
252 | * @param pkey private key of the zone | ||
253 | * @param label name that is being mapped | ||
254 | * @param rd_count number of records in the 'rd' array | ||
255 | * @param rd array of records with data to store | ||
256 | * @param cont continuation to call when done | ||
257 | * @param cont_cls closure for @a cont | ||
258 | * @return handle to abort the request | ||
259 | */ | ||
260 | struct GNUNET_NAMESTORE_QueueEntry * | ||
261 | GNUNET_NAMESTORE_records_commit (struct GNUNET_NAMESTORE_Handle *h, | ||
262 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
263 | const char *label, | ||
264 | unsigned int rd_count, | ||
265 | const struct GNUNET_GNSRECORD_Data *rd, | ||
266 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
267 | void *cont_cls); | ||
268 | |||
269 | /** | ||
215 | * Look for an existing PKEY delegation record for a given public key. | 270 | * Look for an existing PKEY delegation record for a given public key. |
216 | * Returns at most one result to the processor. | 271 | * Returns at most one result to the processor. |
217 | * | 272 | * |
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index 51708dd67..2441b864a 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am | |||
@@ -39,6 +39,7 @@ if HAVE_SQLITE | |||
39 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la | 39 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la |
40 | SQLITE_TESTS = test_plugin_namestore_sqlite \ | 40 | SQLITE_TESTS = test_plugin_namestore_sqlite \ |
41 | test_namestore_api_store_sqlite \ | 41 | test_namestore_api_store_sqlite \ |
42 | test_namestore_api_store_locking_sqlite \ | ||
42 | test_namestore_api_store_update_sqlite \ | 43 | test_namestore_api_store_update_sqlite \ |
43 | test_namestore_api_zone_iteration_sqlite \ | 44 | test_namestore_api_zone_iteration_sqlite \ |
44 | test_namestore_api_remove_sqlite \ | 45 | test_namestore_api_remove_sqlite \ |
@@ -249,6 +250,16 @@ test_namestore_api_store_sqlite_LDADD = \ | |||
249 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 250 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
250 | libgnunetnamestore.la | 251 | libgnunetnamestore.la |
251 | 252 | ||
253 | test_namestore_api_store_locking_sqlite_SOURCES = \ | ||
254 | test_namestore_api_store_locking.c | ||
255 | test_namestore_api_store_locking_sqlite_LDADD = \ | ||
256 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
257 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
258 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
259 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
260 | libgnunetnamestore.la | ||
261 | |||
262 | |||
252 | test_namestore_api_store_postgres_SOURCES = \ | 263 | test_namestore_api_store_postgres_SOURCES = \ |
253 | test_namestore_api_store.c | 264 | test_namestore_api_store.c |
254 | test_namestore_api_store_postgres_LDADD = \ | 265 | test_namestore_api_store_postgres_LDADD = \ |
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index 2a3a006e8..3f679cacd 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c | |||
@@ -121,6 +121,23 @@ struct ZoneIteration | |||
121 | int send_end; | 121 | int send_end; |
122 | }; | 122 | }; |
123 | 123 | ||
124 | /** | ||
125 | * Lock on a record set | ||
126 | */ | ||
127 | struct RecordsLock | ||
128 | { | ||
129 | /* DLL */ | ||
130 | struct RecordsLock *prev; | ||
131 | |||
132 | /* DLL */ | ||
133 | struct RecordsLock *next; | ||
134 | |||
135 | /* Hash of the locked label */ | ||
136 | struct GNUNET_HashCode label_hash; | ||
137 | |||
138 | /* Client locking the zone */ | ||
139 | struct NamestoreClient *client; | ||
140 | }; | ||
124 | 141 | ||
125 | /** | 142 | /** |
126 | * A namestore client | 143 | * A namestore client |
@@ -394,6 +411,16 @@ static struct StoreActivity *sa_head; | |||
394 | static struct StoreActivity *sa_tail; | 411 | static struct StoreActivity *sa_tail; |
395 | 412 | ||
396 | /** | 413 | /** |
414 | * Head of the DLL of record set locks | ||
415 | */ | ||
416 | static struct RecordsLock *locks_head; | ||
417 | |||
418 | /** | ||
419 | * Tail of the DLL of record set locks | ||
420 | */ | ||
421 | static struct RecordsLock *locks_tail; | ||
422 | |||
423 | /** | ||
397 | * Notification context shared by all monitors. | 424 | * Notification context shared by all monitors. |
398 | */ | 425 | */ |
399 | static struct GNUNET_NotificationContext *monitor_nc; | 426 | static struct GNUNET_NotificationContext *monitor_nc; |
@@ -420,6 +447,7 @@ static void | |||
420 | cleanup_task (void *cls) | 447 | cleanup_task (void *cls) |
421 | { | 448 | { |
422 | struct CacheOperation *cop; | 449 | struct CacheOperation *cop; |
450 | struct RecordsLock *lock; | ||
423 | 451 | ||
424 | (void) cls; | 452 | (void) cls; |
425 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); | 453 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); |
@@ -431,6 +459,14 @@ cleanup_task (void *cls) | |||
431 | GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); | 459 | GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); |
432 | GNUNET_free (cop); | 460 | GNUNET_free (cop); |
433 | } | 461 | } |
462 | while (NULL != (lock = locks_head)) | ||
463 | { | ||
464 | GNUNET_CONTAINER_DLL_remove (locks_head, | ||
465 | locks_tail, | ||
466 | lock); | ||
467 | GNUNET_free (lock); | ||
468 | } | ||
469 | |||
434 | if (NULL != namecache) | 470 | if (NULL != namecache) |
435 | { | 471 | { |
436 | GNUNET_NAMECACHE_disconnect (namecache); | 472 | GNUNET_NAMECACHE_disconnect (namecache); |
@@ -1118,6 +1154,7 @@ client_disconnect_cb (void *cls, | |||
1118 | struct NamestoreClient *nc = app_ctx; | 1154 | struct NamestoreClient *nc = app_ctx; |
1119 | struct ZoneIteration *no; | 1155 | struct ZoneIteration *no; |
1120 | struct CacheOperation *cop; | 1156 | struct CacheOperation *cop; |
1157 | struct RecordsLock *lock; | ||
1121 | 1158 | ||
1122 | (void) cls; | 1159 | (void) cls; |
1123 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); | 1160 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); |
@@ -1168,6 +1205,15 @@ client_disconnect_cb (void *cls, | |||
1168 | for (cop = cop_head; NULL != cop; cop = cop->next) | 1205 | for (cop = cop_head; NULL != cop; cop = cop->next) |
1169 | if (nc == cop->nc) | 1206 | if (nc == cop->nc) |
1170 | cop->nc = NULL; | 1207 | cop->nc = NULL; |
1208 | for (lock = locks_head; NULL != lock; lock = lock->next) | ||
1209 | { | ||
1210 | if (nc != lock->client) | ||
1211 | continue; | ||
1212 | GNUNET_CONTAINER_DLL_remove (locks_head, | ||
1213 | locks_tail, | ||
1214 | lock); | ||
1215 | GNUNET_free (lock); | ||
1216 | } | ||
1171 | GNUNET_free (nc); | 1217 | GNUNET_free (nc); |
1172 | } | 1218 | } |
1173 | 1219 | ||
@@ -1361,6 +1407,7 @@ check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1361 | return GNUNET_OK; | 1407 | return GNUNET_OK; |
1362 | } | 1408 | } |
1363 | 1409 | ||
1410 | |||
1364 | /** | 1411 | /** |
1365 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message | 1412 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message |
1366 | * | 1413 | * |
@@ -1374,13 +1421,14 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1374 | struct GNUNET_MQ_Envelope *env; | 1421 | struct GNUNET_MQ_Envelope *env; |
1375 | struct LabelLookupResponseMessage *llr_msg; | 1422 | struct LabelLookupResponseMessage *llr_msg; |
1376 | struct RecordLookupContext rlc; | 1423 | struct RecordLookupContext rlc; |
1424 | struct RecordsLock *lock; | ||
1425 | struct GNUNET_HashCode label_hash; | ||
1377 | const char *name_tmp; | 1426 | const char *name_tmp; |
1378 | char *res_name; | 1427 | char *res_name; |
1379 | char *conv_name; | 1428 | char *conv_name; |
1380 | uint32_t name_len; | 1429 | uint32_t name_len; |
1381 | int res; | 1430 | int res; |
1382 | 1431 | ||
1383 | name_len = ntohl (ll_msg->label_len); | ||
1384 | name_tmp = (const char *) &ll_msg[1]; | 1432 | name_tmp = (const char *) &ll_msg[1]; |
1385 | GNUNET_SERVICE_client_continue (nc->client); | 1433 | GNUNET_SERVICE_client_continue (nc->client); |
1386 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1434 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1396,6 +1444,52 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1396 | GNUNET_SERVICE_client_drop (nc->client); | 1444 | GNUNET_SERVICE_client_drop (nc->client); |
1397 | return; | 1445 | return; |
1398 | } | 1446 | } |
1447 | name_len = strlen (conv_name) + 1; | ||
1448 | if (GNUNET_YES == ntohl (ll_msg->locking)) | ||
1449 | { | ||
1450 | GNUNET_CRYPTO_hash (conv_name, strlen (conv_name), &label_hash); | ||
1451 | for (lock = locks_head; NULL != lock; lock = lock->next) | ||
1452 | if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash))) | ||
1453 | break; | ||
1454 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1455 | "Record locked: %s\n", (NULL == lock) ? "No" : "Yes"); | ||
1456 | if (NULL != lock) | ||
1457 | { | ||
1458 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1459 | "Client holds lock: %s\n", (lock->client != nc) ? "No" : "Yes"); | ||
1460 | |||
1461 | if (lock->client != nc) | ||
1462 | { | ||
1463 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1464 | "Lock is held by other client on `%s'\n", conv_name); | ||
1465 | env = | ||
1466 | GNUNET_MQ_msg_extra (llr_msg, | ||
1467 | name_len, | ||
1468 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE); | ||
1469 | llr_msg->gns_header.r_id = ll_msg->gns_header.r_id; | ||
1470 | llr_msg->private_key = ll_msg->zone; | ||
1471 | llr_msg->name_len = htons (name_len); | ||
1472 | llr_msg->rd_count = htons (0); | ||
1473 | llr_msg->rd_len = htons (0); | ||
1474 | llr_msg->found = htons (GNUNET_SYSERR); | ||
1475 | GNUNET_memcpy (&llr_msg[1], conv_name, name_len); | ||
1476 | GNUNET_MQ_send (nc->mq, env); | ||
1477 | GNUNET_free (conv_name); | ||
1478 | return; | ||
1479 | } | ||
1480 | } | ||
1481 | else | ||
1482 | { | ||
1483 | lock = GNUNET_new (struct RecordsLock); | ||
1484 | lock->client = nc; | ||
1485 | GNUNET_CRYPTO_hash (conv_name, | ||
1486 | strlen (conv_name), | ||
1487 | &lock->label_hash); | ||
1488 | GNUNET_CONTAINER_DLL_insert (locks_head, | ||
1489 | locks_tail, | ||
1490 | lock); | ||
1491 | } | ||
1492 | } | ||
1399 | rlc.label = conv_name; | 1493 | rlc.label = conv_name; |
1400 | rlc.found = GNUNET_NO; | 1494 | rlc.found = GNUNET_NO; |
1401 | rlc.res_rd_count = 0; | 1495 | rlc.res_rd_count = 0; |
@@ -1407,7 +1501,6 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1407 | conv_name, | 1501 | conv_name, |
1408 | &lookup_it, | 1502 | &lookup_it, |
1409 | &rlc); | 1503 | &rlc); |
1410 | GNUNET_free (conv_name); | ||
1411 | env = | 1504 | env = |
1412 | GNUNET_MQ_msg_extra (llr_msg, | 1505 | GNUNET_MQ_msg_extra (llr_msg, |
1413 | name_len + rlc.rd_ser_len, | 1506 | name_len + rlc.rd_ser_len, |
@@ -1419,16 +1512,18 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1419 | llr_msg->rd_len = htons (rlc.rd_ser_len); | 1512 | llr_msg->rd_len = htons (rlc.rd_ser_len); |
1420 | res_name = (char *) &llr_msg[1]; | 1513 | res_name = (char *) &llr_msg[1]; |
1421 | if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res)) | 1514 | if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res)) |
1422 | llr_msg->found = ntohs (GNUNET_YES); | 1515 | llr_msg->found = htons (GNUNET_YES); |
1423 | else | 1516 | else |
1424 | llr_msg->found = ntohs (GNUNET_NO); | 1517 | llr_msg->found = htons (GNUNET_NO); |
1425 | GNUNET_memcpy (&llr_msg[1], name_tmp, name_len); | 1518 | GNUNET_memcpy (&llr_msg[1], conv_name, name_len); |
1426 | GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len); | 1519 | GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len); |
1427 | GNUNET_MQ_send (nc->mq, env); | 1520 | GNUNET_MQ_send (nc->mq, env); |
1428 | GNUNET_free (rlc.res_rd); | 1521 | GNUNET_free (rlc.res_rd); |
1522 | GNUNET_free (conv_name); | ||
1429 | } | 1523 | } |
1430 | 1524 | ||
1431 | 1525 | ||
1526 | |||
1432 | /** | 1527 | /** |
1433 | * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | 1528 | * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message |
1434 | * | 1529 | * |
@@ -1528,6 +1623,8 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1528 | unsigned int rd_count; | 1623 | unsigned int rd_count; |
1529 | int res; | 1624 | int res; |
1530 | struct StoreActivity *sa; | 1625 | struct StoreActivity *sa; |
1626 | struct RecordsLock *lock; | ||
1627 | struct GNUNET_HashCode label_hash; | ||
1531 | struct GNUNET_TIME_Absolute existing_block_exp; | 1628 | struct GNUNET_TIME_Absolute existing_block_exp; |
1532 | struct GNUNET_TIME_Absolute new_block_exp; | 1629 | struct GNUNET_TIME_Absolute new_block_exp; |
1533 | 1630 | ||
@@ -1552,7 +1649,8 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1552 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1649 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1553 | "Error normalizing name `%s'\n", | 1650 | "Error normalizing name `%s'\n", |
1554 | name_tmp); | 1651 | name_tmp); |
1555 | send_store_response (nc, GNUNET_SYSERR, _("Error normalizing name."), rid); | 1652 | send_store_response (nc, GNUNET_SYSERR, _ ("Error normalizing name."), |
1653 | rid); | ||
1556 | GNUNET_SERVICE_client_continue (nc->client); | 1654 | GNUNET_SERVICE_client_continue (nc->client); |
1557 | return; | 1655 | return; |
1558 | } | 1656 | } |
@@ -1574,11 +1672,28 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1574 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)) | 1672 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)) |
1575 | { | 1673 | { |
1576 | send_store_response (nc, GNUNET_SYSERR, | 1674 | send_store_response (nc, GNUNET_SYSERR, |
1577 | _("Error deserializing records."), rid); | 1675 | _ ("Error deserializing records."), rid); |
1578 | GNUNET_free (conv_name); | 1676 | GNUNET_free (conv_name); |
1579 | GNUNET_SERVICE_client_continue (nc->client); | 1677 | GNUNET_SERVICE_client_continue (nc->client); |
1580 | return; | 1678 | return; |
1581 | } | 1679 | } |
1680 | if (GNUNET_YES == ntohl (rp_msg->locking)) | ||
1681 | { | ||
1682 | GNUNET_CRYPTO_hash (conv_name, strlen (conv_name), &label_hash); | ||
1683 | for (lock = locks_head; NULL != lock; lock = lock->next) | ||
1684 | if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash))) | ||
1685 | break; | ||
1686 | if ((NULL == lock) || | ||
1687 | (lock->client != nc)) | ||
1688 | { | ||
1689 | send_store_response (nc, res, _ ("Record set locked."), rid); | ||
1690 | GNUNET_SERVICE_client_continue (nc->client); | ||
1691 | GNUNET_free (conv_name); | ||
1692 | return; | ||
1693 | } | ||
1694 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1695 | "Client has lock on `%s', continuing.\n", conv_name); | ||
1696 | } | ||
1582 | 1697 | ||
1583 | GNUNET_STATISTICS_update (statistics, | 1698 | GNUNET_STATISTICS_update (statistics, |
1584 | "Well-formed store requests received", | 1699 | "Well-formed store requests received", |
@@ -1683,11 +1798,21 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1683 | if (GNUNET_OK != res) | 1798 | if (GNUNET_OK != res) |
1684 | { | 1799 | { |
1685 | /* store not successful, no need to tell monitors */ | 1800 | /* store not successful, no need to tell monitors */ |
1686 | send_store_response (nc, res, _("Store failed"), rid); | 1801 | send_store_response (nc, res, _ ("Store failed"), rid); |
1687 | GNUNET_SERVICE_client_continue (nc->client); | 1802 | GNUNET_SERVICE_client_continue (nc->client); |
1688 | GNUNET_free (conv_name); | 1803 | GNUNET_free (conv_name); |
1689 | return; | 1804 | return; |
1690 | } | 1805 | } |
1806 | if (GNUNET_YES == ntohl (rp_msg->locking)) | ||
1807 | { | ||
1808 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1809 | "Releasing lock on `%s'\n", conv_name); | ||
1810 | GNUNET_assert (NULL != lock); | ||
1811 | GNUNET_CONTAINER_DLL_remove (locks_head, | ||
1812 | locks_tail, | ||
1813 | lock); | ||
1814 | GNUNET_free (lock); | ||
1815 | } | ||
1691 | 1816 | ||
1692 | sa = GNUNET_malloc (sizeof(struct StoreActivity) | 1817 | sa = GNUNET_malloc (sizeof(struct StoreActivity) |
1693 | + ntohs (rp_msg->gns_header.header.size)); | 1818 | + ntohs (rp_msg->gns_header.header.size)); |
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h index 8391d9d74..0f3ffa837 100644 --- a/src/namestore/namestore.h +++ b/src/namestore/namestore.h | |||
@@ -68,6 +68,11 @@ struct RecordStoreMessage | |||
68 | struct GNUNET_TIME_AbsoluteNBO expire; | 68 | struct GNUNET_TIME_AbsoluteNBO expire; |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Unock the label with this request. | ||
72 | */ | ||
73 | uint32_t locking GNUNET_PACKED; | ||
74 | |||
75 | /** | ||
71 | * Name length | 76 | * Name length |
72 | */ | 77 | */ |
73 | uint16_t name_len GNUNET_PACKED; | 78 | uint16_t name_len GNUNET_PACKED; |
@@ -146,6 +151,11 @@ struct LabelLookupMessage | |||
146 | uint32_t label_len GNUNET_PACKED; | 151 | uint32_t label_len GNUNET_PACKED; |
147 | 152 | ||
148 | /** | 153 | /** |
154 | * Lock the label with this lookup | ||
155 | */ | ||
156 | uint32_t locking GNUNET_PACKED; | ||
157 | |||
158 | /** | ||
149 | * The private key of the zone to look up in | 159 | * The private key of the zone to look up in |
150 | */ | 160 | */ |
151 | struct GNUNET_IDENTITY_PrivateKey zone; | 161 | struct GNUNET_IDENTITY_PrivateKey zone; |
@@ -185,7 +195,7 @@ struct LabelLookupResponseMessage | |||
185 | * Was the label found in the database?? | 195 | * Was the label found in the database?? |
186 | * #GNUNET_YES or #GNUNET_NO | 196 | * #GNUNET_YES or #GNUNET_NO |
187 | */ | 197 | */ |
188 | uint16_t found GNUNET_PACKED; | 198 | int16_t found GNUNET_PACKED; |
189 | 199 | ||
190 | /** | 200 | /** |
191 | * The private key of the authority. | 201 | * The private key of the authority. |
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index 3c8caf961..a7380bbde 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c | |||
@@ -479,8 +479,10 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg) | |||
479 | size_t name_len; | 479 | size_t name_len; |
480 | size_t rd_len; | 480 | size_t rd_len; |
481 | unsigned int rd_count; | 481 | unsigned int rd_count; |
482 | int16_t found = (int16_t) ntohs (msg->found); | ||
482 | 483 | ||
483 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT\n"); | 484 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n", |
485 | found); | ||
484 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | 486 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); |
485 | if (NULL == qe) | 487 | if (NULL == qe) |
486 | return; | 488 | return; |
@@ -488,7 +490,7 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg) | |||
488 | rd_count = ntohs (msg->rd_count); | 490 | rd_count = ntohs (msg->rd_count); |
489 | name_len = ntohs (msg->name_len); | 491 | name_len = ntohs (msg->name_len); |
490 | name = (const char *) &msg[1]; | 492 | name = (const char *) &msg[1]; |
491 | if (GNUNET_NO == ntohs (msg->found)) | 493 | if (GNUNET_NO == found) |
492 | { | 494 | { |
493 | /* label was not in namestore */ | 495 | /* label was not in namestore */ |
494 | if (NULL != qe->proc) | 496 | if (NULL != qe->proc) |
@@ -496,6 +498,13 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg) | |||
496 | free_qe (qe); | 498 | free_qe (qe); |
497 | return; | 499 | return; |
498 | } | 500 | } |
501 | if (GNUNET_SYSERR == found) | ||
502 | { | ||
503 | if (NULL != qe->error_cb) | ||
504 | qe->error_cb (qe->error_cb_cls); | ||
505 | free_qe (qe); | ||
506 | return; | ||
507 | } | ||
499 | 508 | ||
500 | rd_tmp = &name[name_len]; | 509 | rd_tmp = &name[name_len]; |
501 | { | 510 | { |
@@ -1005,14 +1014,15 @@ warn_delay (void *cls) | |||
1005 | } | 1014 | } |
1006 | 1015 | ||
1007 | struct GNUNET_NAMESTORE_QueueEntry * | 1016 | struct GNUNET_NAMESTORE_QueueEntry * |
1008 | GNUNET_NAMESTORE_records_store ( | 1017 | records_store_ ( |
1009 | struct GNUNET_NAMESTORE_Handle *h, | 1018 | struct GNUNET_NAMESTORE_Handle *h, |
1010 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | 1019 | const struct GNUNET_IDENTITY_PrivateKey *pkey, |
1011 | const char *label, | 1020 | const char *label, |
1012 | unsigned int rd_count, | 1021 | unsigned int rd_count, |
1013 | const struct GNUNET_GNSRECORD_Data *rd, | 1022 | const struct GNUNET_GNSRECORD_Data *rd, |
1014 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | 1023 | GNUNET_NAMESTORE_ContinuationWithStatus cont, |
1015 | void *cont_cls) | 1024 | void *cont_cls, |
1025 | int locking) | ||
1016 | { | 1026 | { |
1017 | struct GNUNET_NAMESTORE_QueueEntry *qe; | 1027 | struct GNUNET_NAMESTORE_QueueEntry *qe; |
1018 | struct GNUNET_MQ_Envelope *env; | 1028 | struct GNUNET_MQ_Envelope *env; |
@@ -1059,6 +1069,7 @@ GNUNET_NAMESTORE_records_store ( | |||
1059 | msg->rd_len = htons (rd_ser_len); | 1069 | msg->rd_len = htons (rd_ser_len); |
1060 | msg->reserved = ntohs(0); | 1070 | msg->reserved = ntohs(0); |
1061 | msg->private_key = *pkey; | 1071 | msg->private_key = *pkey; |
1072 | msg->locking = htonl (locking); | ||
1062 | 1073 | ||
1063 | name_tmp = (char *) &msg[1]; | 1074 | name_tmp = (char *) &msg[1]; |
1064 | GNUNET_memcpy (name_tmp, label, name_len); | 1075 | GNUNET_memcpy (name_tmp, label, name_len); |
@@ -1090,27 +1101,45 @@ GNUNET_NAMESTORE_records_store ( | |||
1090 | return qe; | 1101 | return qe; |
1091 | } | 1102 | } |
1092 | 1103 | ||
1093 | /** | ||
1094 | * Lookup an item in the namestore. | ||
1095 | * | ||
1096 | * @param h handle to the namestore | ||
1097 | * @param pkey private key of the zone | ||
1098 | * @param label name that is being mapped (at most 255 characters long) | ||
1099 | * @param error_cb function to call on error (i.e. disconnect) | ||
1100 | * @param error_cb_cls closure for @a error_cb | ||
1101 | * @param rm function to call with the result (with 0 records if we don't have that label) | ||
1102 | * @param rm_cls closure for @a rm | ||
1103 | * @return handle to abort the request | ||
1104 | */ | ||
1105 | struct GNUNET_NAMESTORE_QueueEntry * | 1104 | struct GNUNET_NAMESTORE_QueueEntry * |
1106 | GNUNET_NAMESTORE_records_lookup ( | 1105 | GNUNET_NAMESTORE_records_store ( |
1106 | struct GNUNET_NAMESTORE_Handle *h, | ||
1107 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1108 | const char *label, | ||
1109 | unsigned int rd_count, | ||
1110 | const struct GNUNET_GNSRECORD_Data *rd, | ||
1111 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1112 | void *cont_cls) | ||
1113 | { | ||
1114 | return records_store_ (h, pkey, label, | ||
1115 | rd_count, rd, cont, cont_cls, GNUNET_NO); | ||
1116 | } | ||
1117 | |||
1118 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1119 | GNUNET_NAMESTORE_records_commit ( | ||
1120 | struct GNUNET_NAMESTORE_Handle *h, | ||
1121 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1122 | const char *label, | ||
1123 | unsigned int rd_count, | ||
1124 | const struct GNUNET_GNSRECORD_Data *rd, | ||
1125 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1126 | void *cont_cls) | ||
1127 | { | ||
1128 | return records_store_ (h, pkey, label, | ||
1129 | rd_count, rd, cont, cont_cls, GNUNET_YES); | ||
1130 | } | ||
1131 | |||
1132 | |||
1133 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1134 | records_lookup_ ( | ||
1107 | struct GNUNET_NAMESTORE_Handle *h, | 1135 | struct GNUNET_NAMESTORE_Handle *h, |
1108 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | 1136 | const struct GNUNET_IDENTITY_PrivateKey *pkey, |
1109 | const char *label, | 1137 | const char *label, |
1110 | GNUNET_SCHEDULER_TaskCallback error_cb, | 1138 | GNUNET_SCHEDULER_TaskCallback error_cb, |
1111 | void *error_cb_cls, | 1139 | void *error_cb_cls, |
1112 | GNUNET_NAMESTORE_RecordMonitor rm, | 1140 | GNUNET_NAMESTORE_RecordMonitor rm, |
1113 | void *rm_cls) | 1141 | void *rm_cls, |
1142 | int locking) | ||
1114 | { | 1143 | { |
1115 | struct GNUNET_NAMESTORE_QueueEntry *qe; | 1144 | struct GNUNET_NAMESTORE_QueueEntry *qe; |
1116 | struct GNUNET_MQ_Envelope *env; | 1145 | struct GNUNET_MQ_Envelope *env; |
@@ -1138,6 +1167,7 @@ GNUNET_NAMESTORE_records_lookup ( | |||
1138 | msg->gns_header.r_id = htonl (qe->op_id); | 1167 | msg->gns_header.r_id = htonl (qe->op_id); |
1139 | msg->zone = *pkey; | 1168 | msg->zone = *pkey; |
1140 | msg->label_len = htonl (label_len); | 1169 | msg->label_len = htonl (label_len); |
1170 | msg->locking = htonl (locking); | ||
1141 | GNUNET_memcpy (&msg[1], label, label_len); | 1171 | GNUNET_memcpy (&msg[1], label, label_len); |
1142 | if (NULL == h->mq) | 1172 | if (NULL == h->mq) |
1143 | qe->env = env; | 1173 | qe->env = env; |
@@ -1146,22 +1176,34 @@ GNUNET_NAMESTORE_records_lookup ( | |||
1146 | return qe; | 1176 | return qe; |
1147 | } | 1177 | } |
1148 | 1178 | ||
1179 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1180 | GNUNET_NAMESTORE_records_lookup ( | ||
1181 | struct GNUNET_NAMESTORE_Handle *h, | ||
1182 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1183 | const char *label, | ||
1184 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1185 | void *error_cb_cls, | ||
1186 | GNUNET_NAMESTORE_RecordMonitor rm, | ||
1187 | void *rm_cls) | ||
1188 | { | ||
1189 | return records_lookup_ (h, pkey, label, | ||
1190 | error_cb, error_cb_cls, rm, rm_cls, GNUNET_NO); | ||
1191 | } | ||
1192 | |||
1193 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1194 | GNUNET_NAMESTORE_records_open ( | ||
1195 | struct GNUNET_NAMESTORE_Handle *h, | ||
1196 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1197 | const char *label, | ||
1198 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1199 | void *error_cb_cls, | ||
1200 | GNUNET_NAMESTORE_RecordMonitor rm, | ||
1201 | void *rm_cls) | ||
1202 | { | ||
1203 | return records_lookup_ (h, pkey, label, | ||
1204 | error_cb, error_cb_cls, rm, rm_cls, GNUNET_YES); | ||
1205 | } | ||
1149 | 1206 | ||
1150 | /** | ||
1151 | * Look for an existing PKEY delegation record for a given public key. | ||
1152 | * Returns at most one result to the processor. | ||
1153 | * | ||
1154 | * @param h handle to the namestore | ||
1155 | * @param zone public key of the zone to look up in, never NULL | ||
1156 | * @param value_zone public key of the target zone (value), never NULL | ||
1157 | * @param error_cb function to call on error (i.e. disconnect) | ||
1158 | * @param error_cb_cls closure for @a error_cb | ||
1159 | * @param proc function to call on the matching records, or with | ||
1160 | * NULL (rd_count == 0) if there are no matching records | ||
1161 | * @param proc_cls closure for @a proc | ||
1162 | * @return a handle that can be used to | ||
1163 | * cancel | ||
1164 | */ | ||
1165 | struct GNUNET_NAMESTORE_QueueEntry * | 1207 | struct GNUNET_NAMESTORE_QueueEntry * |
1166 | GNUNET_NAMESTORE_zone_to_name ( | 1208 | GNUNET_NAMESTORE_zone_to_name ( |
1167 | struct GNUNET_NAMESTORE_Handle *h, | 1209 | struct GNUNET_NAMESTORE_Handle *h, |