aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/gnunet-service-namestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/gnunet-service-namestore.c')
-rw-r--r--src/namestore/gnunet-service-namestore.c396
1 files changed, 352 insertions, 44 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index 9b2d9b6f3..d735822fb 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 */
127struct 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;
394static struct StoreActivity *sa_tail; 411static struct StoreActivity *sa_tail;
395 412
396/** 413/**
414 * Head of the DLL of record set locks
415 */
416static struct RecordsLock *locks_head;
417
418/**
419 * Tail of the DLL of record set locks
420 */
421static struct RecordsLock *locks_tail;
422
423/**
397 * Notification context shared by all monitors. 424 * Notification context shared by all monitors.
398 */ 425 */
399static struct GNUNET_NotificationContext *monitor_nc; 426static struct GNUNET_NotificationContext *monitor_nc;
@@ -420,6 +447,7 @@ static void
420cleanup_task (void *cls) 447cleanup_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);
@@ -808,7 +844,8 @@ send_lookup_response (struct NamestoreClient *nc,
808 * @param rid client's request ID 844 * @param rid client's request ID
809 */ 845 */
810static void 846static void
811send_store_response (struct NamestoreClient *nc, int res, uint32_t rid) 847send_store_response (struct NamestoreClient *nc, int res, const char*emsg,
848 uint32_t rid)
812{ 849{
813 struct GNUNET_MQ_Envelope *env; 850 struct GNUNET_MQ_Envelope *env;
814 struct RecordStoreResponseMessage *rcr_msg; 851 struct RecordStoreResponseMessage *rcr_msg;
@@ -820,10 +857,17 @@ send_store_response (struct NamestoreClient *nc, int res, uint32_t rid)
820 "Store requests completed", 857 "Store requests completed",
821 1, 858 1,
822 GNUNET_NO); 859 GNUNET_NO);
823 env = GNUNET_MQ_msg (rcr_msg, 860 env = GNUNET_MQ_msg_extra (rcr_msg,
824 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE); 861 (NULL != emsg) ? strlen (emsg) + 1 : 0,
862 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
825 rcr_msg->gns_header.r_id = htonl (rid); 863 rcr_msg->gns_header.r_id = htonl (rid);
826 rcr_msg->op_result = htonl (res); 864 rcr_msg->op_result = htonl (res);
865 rcr_msg->reserved = htons (0);
866 if (NULL != emsg)
867 {
868 rcr_msg->emsg_len = htons (strlen (emsg) + 1);
869 memcpy (&rcr_msg[1], emsg, strlen (emsg) + 1);
870 }
827 GNUNET_MQ_send (nc->mq, env); 871 GNUNET_MQ_send (nc->mq, env);
828} 872}
829 873
@@ -874,7 +918,7 @@ finish_cache_operation (void *cls, int32_t success, const char *emsg)
874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n"); 918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n");
875 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); 919 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
876 if (NULL != cop->nc) 920 if (NULL != cop->nc)
877 send_store_response (cop->nc, success, cop->rid); 921 send_store_response (cop->nc, success, emsg, cop->rid);
878 if (NULL != (zi = cop->zi)) 922 if (NULL != (zi = cop->zi))
879 { 923 {
880 zi->cache_ops--; 924 zi->cache_ops--;
@@ -910,29 +954,40 @@ refresh_block (struct NamestoreClient *nc,
910 const struct GNUNET_GNSRECORD_Data *rd) 954 const struct GNUNET_GNSRECORD_Data *rd)
911{ 955{
912 struct GNUNET_GNSRECORD_Block *block; 956 struct GNUNET_GNSRECORD_Block *block;
957 struct GNUNET_GNSRECORD_Data rd_clean[rd_count];
913 struct CacheOperation *cop; 958 struct CacheOperation *cop;
914 struct GNUNET_IDENTITY_PublicKey pkey; 959 struct GNUNET_IDENTITY_PublicKey pkey;
915 struct GNUNET_GNSRECORD_Data *nick; 960 struct GNUNET_GNSRECORD_Data *nick;
916 struct GNUNET_GNSRECORD_Data *res; 961 struct GNUNET_GNSRECORD_Data *res;
917 unsigned int res_count; 962 unsigned int res_count;
963 unsigned int rd_count_clean;
918 struct GNUNET_TIME_Absolute exp_time; 964 struct GNUNET_TIME_Absolute exp_time;
919 965
966 /** Do not block-cache tombstones */
967 rd_count_clean = 0;
968 for (int i = 0; i < rd_count; i++)
969 {
970 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
971 continue;
972 rd_clean[rd_count_clean++] = rd[i];
973 }
974
920 nick = get_nick_record (zone_key); 975 nick = get_nick_record (zone_key);
921 res_count = rd_count; 976 res_count = rd_count_clean;
922 res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */ 977 res = (struct GNUNET_GNSRECORD_Data *) rd_clean; /* fixme: a bit unclean... */
923 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) 978 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
924 { 979 {
925 nick->flags = 980 nick->flags =
926 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; 981 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
927 merge_with_nick_records (nick, rd_count, rd, &res_count, &res); 982 merge_with_nick_records (nick, rd_count_clean, rd_clean, &res_count, &res);
928 } 983 }
929 if (NULL != nick) 984 if (NULL != nick)
930 GNUNET_free (nick); 985 GNUNET_free (nick);
931 if (0 == res_count) 986 if (0 == res_count)
932 { 987 {
933 if (NULL != nc) 988 if (NULL != nc)
934 send_store_response (nc, GNUNET_OK, rid); 989 send_store_response (nc, GNUNET_OK, NULL, rid);
935 if (rd != res) 990 if (rd_clean != res)
936 GNUNET_free (res); 991 GNUNET_free (res);
937 return; /* no data, no need to update cache */ 992 return; /* no data, no need to update cache */
938 } 993 }
@@ -943,20 +998,21 @@ refresh_block (struct NamestoreClient *nc,
943 1, 998 1,
944 GNUNET_NO); 999 GNUNET_NO);
945 if (NULL != nc) 1000 if (NULL != nc)
946 send_store_response (nc, GNUNET_OK, rid); 1001 send_store_response (nc, GNUNET_OK, NULL, rid);
947 if (rd != res) 1002 if (rd_clean != res)
948 GNUNET_free (res); 1003 GNUNET_free (res);
949 return; 1004 return;
950 } 1005 }
951 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res); 1006 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res,
1007 GNUNET_TIME_UNIT_ZERO_ABS);
952 if (cache_keys) 1008 if (cache_keys)
953 GNUNET_assert (GNUNET_OK == 1009 GNUNET_assert (GNUNET_OK ==
954 GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name, 1010 GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name,
955 res, res_count, &block)); 1011 res, res_count, &block));
956 else 1012 else
957 GNUNET_assert (GNUNET_OK == 1013 GNUNET_assert (GNUNET_OK ==
958 GNUNET_GNSRECORD_block_create (zone_key, exp_time, name, 1014 GNUNET_GNSRECORD_block_create (zone_key, exp_time, name,
959 res, res_count, &block)); 1015 res, res_count, &block));
960 GNUNET_assert (NULL != block); 1016 GNUNET_assert (NULL != block);
961 GNUNET_IDENTITY_key_get_public (zone_key, &pkey); 1017 GNUNET_IDENTITY_key_get_public (zone_key, &pkey);
962 GNUNET_log ( 1018 GNUNET_log (
@@ -974,7 +1030,7 @@ refresh_block (struct NamestoreClient *nc,
974 cop->nc = nc; 1030 cop->nc = nc;
975 cop->zi = zi; 1031 cop->zi = zi;
976 if (NULL != zi) 1032 if (NULL != zi)
977 zi->cache_ops++; 1033 zi->cache_ops ++;
978 cop->rid = rid; 1034 cop->rid = rid;
979 GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop); 1035 GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop);
980 cop->qe = GNUNET_NAMECACHE_block_cache (namecache, 1036 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
@@ -982,7 +1038,7 @@ refresh_block (struct NamestoreClient *nc,
982 &finish_cache_operation, 1038 &finish_cache_operation,
983 cop); 1039 cop);
984 GNUNET_free (block); 1040 GNUNET_free (block);
985 if (rd != res) 1041 if (rd_clean != res)
986 GNUNET_free (res); 1042 GNUNET_free (res);
987} 1043}
988 1044
@@ -1098,6 +1154,7 @@ client_disconnect_cb (void *cls,
1098 struct NamestoreClient *nc = app_ctx; 1154 struct NamestoreClient *nc = app_ctx;
1099 struct ZoneIteration *no; 1155 struct ZoneIteration *no;
1100 struct CacheOperation *cop; 1156 struct CacheOperation *cop;
1157 struct RecordsLock *lock;
1101 1158
1102 (void) cls; 1159 (void) cls;
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); 1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
@@ -1148,6 +1205,15 @@ client_disconnect_cb (void *cls,
1148 for (cop = cop_head; NULL != cop; cop = cop->next) 1205 for (cop = cop_head; NULL != cop; cop = cop->next)
1149 if (nc == cop->nc) 1206 if (nc == cop->nc)
1150 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 }
1151 GNUNET_free (nc); 1217 GNUNET_free (nc);
1152} 1218}
1153 1219
@@ -1341,6 +1407,105 @@ check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1341 return GNUNET_OK; 1407 return GNUNET_OK;
1342} 1408}
1343 1409
1410static void
1411calculate_lock_hash (const char *label,
1412 const struct GNUNET_IDENTITY_PrivateKey *zone,
1413 struct GNUNET_HashCode *result)
1414{
1415 struct GNUNET_HashContext *hctx;
1416
1417 hctx = GNUNET_CRYPTO_hash_context_start ();
1418 GNUNET_CRYPTO_hash_context_read (hctx, label, strlen (label));
1419 GNUNET_CRYPTO_hash_context_read (hctx, zone,
1420 sizeof (*zone));
1421 GNUNET_CRYPTO_hash_context_finish (hctx, result);
1422}
1423
1424/**
1425 * Release a lock on a record set.
1426 * Does nothing if lock not held.
1427 *
1428 * @param label the label of the record set
1429 * @param zone the zone
1430 * @param nc the client releasing the lock
1431 */
1432static void
1433NST_label_lock_release (const char *label,
1434 const struct GNUNET_IDENTITY_PrivateKey *zone,
1435 const struct NamestoreClient *nc)
1436{
1437 struct GNUNET_HashCode label_hash;
1438 struct RecordsLock *lock;
1439
1440 calculate_lock_hash (label, zone, &label_hash);
1441 for (lock = locks_head; NULL != lock; lock = lock->next)
1442 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1443 break;
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1445 "Record locked: %s\n", (NULL == lock) ? "No" : "Yes");
1446 if (NULL == lock)
1447 return;
1448 if (lock->client != nc)
1449 {
1450 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1451 "Lock is held by other client on `%s'\n", label);
1452 return;
1453 }
1454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1455 "Unocking %s\n", GNUNET_h2s (&label_hash));
1456 GNUNET_CONTAINER_DLL_remove (locks_head,
1457 locks_tail,
1458 lock);
1459 GNUNET_free (lock);
1460}
1461
1462/**
1463 * Get/set a lock on a record set.
1464 * May be called multiple times but will
1465 * not aquire additional locks.
1466 *
1467 * @param the label of the record set
1468 * @param the zone
1469 * @param the client doing the locking
1470 * @return GNUNET_YES if lock retrieved or set already.
1471 */
1472static enum GNUNET_GenericReturnValue
1473NST_label_lock (const char *label,
1474 const struct GNUNET_IDENTITY_PrivateKey *zone,
1475 struct NamestoreClient *nc)
1476{
1477 struct GNUNET_HashCode label_hash;
1478 struct RecordsLock *lock;
1479
1480 calculate_lock_hash (label, zone, &label_hash);
1481 for (lock = locks_head; NULL != lock; lock = lock->next)
1482 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1483 break;
1484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1485 "Record locked: %s\n", (NULL == lock) ? "No" : "Yes");
1486 if (NULL != lock)
1487 {
1488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1489 "Client holds lock: %s\n", (lock->client != nc) ? "No" : "Yes");
1490 if (lock->client != nc)
1491 {
1492 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1493 "Lock is held by other client on `%s'\n", label);
1494 return GNUNET_NO;
1495 }
1496 return GNUNET_YES;
1497 }
1498 lock = GNUNET_new (struct RecordsLock);
1499 lock->client = nc;
1500 memcpy (&lock->label_hash, &label_hash, sizeof (label_hash));
1501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1502 "Locking %s\n", GNUNET_h2s (&label_hash));
1503 GNUNET_CONTAINER_DLL_insert (locks_head,
1504 locks_tail,
1505 lock);
1506 return GNUNET_YES;
1507}
1508
1344 1509
1345/** 1510/**
1346 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message 1511 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
@@ -1355,13 +1520,14 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1355 struct GNUNET_MQ_Envelope *env; 1520 struct GNUNET_MQ_Envelope *env;
1356 struct LabelLookupResponseMessage *llr_msg; 1521 struct LabelLookupResponseMessage *llr_msg;
1357 struct RecordLookupContext rlc; 1522 struct RecordLookupContext rlc;
1523 struct RecordsLock *lock;
1524 struct GNUNET_HashCode label_hash;
1358 const char *name_tmp; 1525 const char *name_tmp;
1359 char *res_name; 1526 char *res_name;
1360 char *conv_name; 1527 char *conv_name;
1361 uint32_t name_len; 1528 uint32_t name_len;
1362 int res; 1529 int res;
1363 1530
1364 name_len = ntohl (ll_msg->label_len);
1365 name_tmp = (const char *) &ll_msg[1]; 1531 name_tmp = (const char *) &ll_msg[1];
1366 GNUNET_SERVICE_client_continue (nc->client); 1532 GNUNET_SERVICE_client_continue (nc->client);
1367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1377,6 +1543,29 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1377 GNUNET_SERVICE_client_drop (nc->client); 1543 GNUNET_SERVICE_client_drop (nc->client);
1378 return; 1544 return;
1379 } 1545 }
1546 name_len = strlen (conv_name) + 1;
1547 if (GNUNET_YES == ntohl (ll_msg->locking))
1548 {
1549 if (GNUNET_NO == NST_label_lock (conv_name, &ll_msg->zone, nc))
1550 {
1551 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1552 "Lock is held by other client on `%s'\n", conv_name);
1553 env =
1554 GNUNET_MQ_msg_extra (llr_msg,
1555 name_len,
1556 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1557 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1558 llr_msg->private_key = ll_msg->zone;
1559 llr_msg->name_len = htons (name_len);
1560 llr_msg->rd_count = htons (0);
1561 llr_msg->rd_len = htons (0);
1562 llr_msg->found = htons (GNUNET_SYSERR);
1563 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1564 GNUNET_MQ_send (nc->mq, env);
1565 GNUNET_free (conv_name);
1566 return;
1567 }
1568 }
1380 rlc.label = conv_name; 1569 rlc.label = conv_name;
1381 rlc.found = GNUNET_NO; 1570 rlc.found = GNUNET_NO;
1382 rlc.res_rd_count = 0; 1571 rlc.res_rd_count = 0;
@@ -1388,7 +1577,6 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1388 conv_name, 1577 conv_name,
1389 &lookup_it, 1578 &lookup_it,
1390 &rlc); 1579 &rlc);
1391 GNUNET_free (conv_name);
1392 env = 1580 env =
1393 GNUNET_MQ_msg_extra (llr_msg, 1581 GNUNET_MQ_msg_extra (llr_msg,
1394 name_len + rlc.rd_ser_len, 1582 name_len + rlc.rd_ser_len,
@@ -1400,16 +1588,18 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1400 llr_msg->rd_len = htons (rlc.rd_ser_len); 1588 llr_msg->rd_len = htons (rlc.rd_ser_len);
1401 res_name = (char *) &llr_msg[1]; 1589 res_name = (char *) &llr_msg[1];
1402 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res)) 1590 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1403 llr_msg->found = ntohs (GNUNET_YES); 1591 llr_msg->found = htons (GNUNET_YES);
1404 else 1592 else
1405 llr_msg->found = ntohs (GNUNET_NO); 1593 llr_msg->found = htons (GNUNET_NO);
1406 GNUNET_memcpy (&llr_msg[1], name_tmp, name_len); 1594 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1407 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len); 1595 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len);
1408 GNUNET_MQ_send (nc->mq, env); 1596 GNUNET_MQ_send (nc->mq, env);
1409 GNUNET_free (rlc.res_rd); 1597 GNUNET_free (rlc.res_rd);
1598 GNUNET_free (conv_name);
1410} 1599}
1411 1600
1412 1601
1602
1413/** 1603/**
1414 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message 1604 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1415 * 1605 *
@@ -1452,6 +1642,45 @@ check_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1452 1642
1453 1643
1454/** 1644/**
1645 * Check if set contains a tombstone, store if necessary
1646 *
1647 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
1648 * @param seq sequence number of the record, MUST NOT BE ZERO
1649 * @param private_key the private key of the zone (unused)
1650 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
1651 * @param rd_count number of records in @a rd
1652 * @param rd records stored under @a label in the zone
1653 */
1654static void
1655get_block_exp_existing (void *cls,
1656 uint64_t seq,
1657 const struct
1658 GNUNET_IDENTITY_PrivateKey *private_key,
1659 const char *label,
1660 unsigned int rd_count,
1661 const struct GNUNET_GNSRECORD_Data *rd)
1662{
1663 struct GNUNET_TIME_Absolute *exp = cls;
1664 struct GNUNET_GNSRECORD_Data rd_pub[rd_count];
1665 unsigned int rd_pub_count;
1666 char *emsg;
1667
1668 if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label,
1669 rd,
1670 rd_count,
1671 rd_pub,
1672 &rd_pub_count,
1673 exp,
1674 &emsg))
1675 {
1676 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1677 "%s\n", emsg);
1678 GNUNET_free (emsg);
1679 }
1680}
1681
1682
1683/**
1455 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message 1684 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1456 * 1685 *
1457 * @param cls client sending the message 1686 * @param cls client sending the message
@@ -1470,37 +1699,75 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1470 unsigned int rd_count; 1699 unsigned int rd_count;
1471 int res; 1700 int res;
1472 struct StoreActivity *sa; 1701 struct StoreActivity *sa;
1702 struct RecordsLock *lock;
1703 struct GNUNET_HashCode label_hash;
1704 struct GNUNET_TIME_Absolute existing_block_exp;
1705 struct GNUNET_TIME_Absolute new_block_exp;
1473 1706
1474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1475 "Received NAMESTORE_RECORD_STORE message\n"); 1708 "Received NAMESTORE_RECORD_STORE message\n");
1709 existing_block_exp = GNUNET_TIME_UNIT_ZERO_ABS;
1710 new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS;
1476 rid = ntohl (rp_msg->gns_header.r_id); 1711 rid = ntohl (rp_msg->gns_header.r_id);
1477 name_len = ntohs (rp_msg->name_len); 1712 name_len = ntohs (rp_msg->name_len);
1478 rd_count = ntohs (rp_msg->rd_count); 1713 rd_count = ntohs (rp_msg->rd_count);
1479 rd_ser_len = ntohs (rp_msg->rd_len); 1714 rd_ser_len = ntohs (rp_msg->rd_len);
1480 GNUNET_break (0 == ntohs (rp_msg->reserved));
1481 name_tmp = (const char *) &rp_msg[1]; 1715 name_tmp = (const char *) &rp_msg[1];
1482 rd_ser = &name_tmp[name_len]; 1716 rd_ser = &name_tmp[name_len];
1483 { 1717 {
1484 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; 1718 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1485 1719 char *emsg;
1486 if (GNUNET_OK !=
1487 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1488 {
1489 GNUNET_break (0);
1490 GNUNET_SERVICE_client_drop (nc->client);
1491 return;
1492 }
1493 1720
1494 /* Extracting and converting private key */ 1721 /* Extracting and converting private key */
1495 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); 1722 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
1496 if (NULL == conv_name) 1723 if (NULL == conv_name)
1497 { 1724 {
1498 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1725 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1499 "Error converting name `%s'\n", 1726 "Error normalizing name `%s'\n",
1500 name_tmp); 1727 name_tmp);
1501 GNUNET_SERVICE_client_drop (nc->client); 1728 send_store_response (nc, GNUNET_SYSERR, _ ("Error normalizing name."),
1729 rid);
1730 GNUNET_SERVICE_client_continue (nc->client);
1731 return;
1732 }
1733
1734 /* Check name for validity */
1735 if (GNUNET_OK != GNUNET_GNSRECORD_label_check (conv_name, &emsg))
1736 {
1737 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1738 "Label invalid: `%s'\n",
1739 emsg);
1740 send_store_response (nc, GNUNET_SYSERR, emsg, rid);
1741 GNUNET_free (emsg);
1742 GNUNET_free (conv_name);
1743 GNUNET_SERVICE_client_continue (nc->client);
1744 return;
1745 }
1746
1747 if (GNUNET_OK !=
1748 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1749 {
1750 send_store_response (nc, GNUNET_SYSERR,
1751 _ ("Error deserializing records."), rid);
1752 GNUNET_free (conv_name);
1753 GNUNET_SERVICE_client_continue (nc->client);
1502 return; 1754 return;
1503 } 1755 }
1756 if (GNUNET_YES == ntohl (rp_msg->locking))
1757 {
1758 if (GNUNET_NO == NST_label_lock (conv_name, &rp_msg->private_key, nc))
1759 {
1760 send_store_response (nc, GNUNET_SYSERR, _ ("Record set locked."), rid);
1761 GNUNET_SERVICE_client_continue (nc->client);
1762 GNUNET_free (conv_name);
1763 return;
1764 }
1765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1766 "Client has lock on `%s', continuing.\n", conv_name);
1767 if (GNUNET_YES == ntohl (rp_msg->locking))
1768 NST_label_lock_release (conv_name, &rp_msg->private_key, nc);
1769 }
1770
1504 GNUNET_STATISTICS_update (statistics, 1771 GNUNET_STATISTICS_update (statistics,
1505 "Well-formed store requests received", 1772 "Well-formed store requests received",
1506 1, 1773 1,
@@ -1509,12 +1776,12 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1509 "Creating %u records for name `%s'\n", 1776 "Creating %u records for name `%s'\n",
1510 (unsigned int) rd_count, 1777 (unsigned int) rd_count,
1511 conv_name); 1778 conv_name);
1512 if ((0 == rd_count) && 1779 if ((GNUNET_NO == GSN_database->lookup_records (GSN_database->cls,
1513 (GNUNET_NO == GSN_database->lookup_records (GSN_database->cls,
1514 &rp_msg->private_key, 1780 &rp_msg->private_key,
1515 conv_name, 1781 conv_name,
1516 NULL, 1782 &get_block_exp_existing,
1517 0))) 1783 &existing_block_exp)) &&
1784 (rd_count == 0))
1518 { 1785 {
1519 /* This name does not exist, so cannot be removed */ 1786 /* This name does not exist, so cannot be removed */
1520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1525,9 +1792,18 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1525 else 1792 else
1526 { 1793 {
1527 /* remove "NICK" records, unless this is for the 1794 /* remove "NICK" records, unless this is for the
1528 #GNUNET_GNS_EMPTY_LABEL_AT label */ 1795 #GNUNET_GNS_EMPTY_LABEL_AT label
1796 We may need one additional record later for tombstone.
1797 FIXME: Since we must normalize the record set (check for
1798 consistency etc) we have to iterate the set twice.
1799 May be inefficient.
1800 We cannot really move the nick caching into GNSRECORD.
1801 */
1529 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)]; 1802 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)];
1803 struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1];
1530 unsigned int rd_clean_off; 1804 unsigned int rd_clean_off;
1805 unsigned int rd_nf_count;
1806 char *emsg;
1531 int have_nick; 1807 int have_nick;
1532 1808
1533 rd_clean_off = 0; 1809 rd_clean_off = 0;
@@ -1535,6 +1811,7 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1535 for (unsigned int i = 0; i < rd_count; i++) 1811 for (unsigned int i = 0; i < rd_count; i++)
1536 { 1812 {
1537 rd_clean[rd_clean_off] = rd[i]; 1813 rd_clean[rd_clean_off] = rd[i];
1814
1538 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) || 1815 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) ||
1539 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type)) 1816 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type))
1540 rd_clean_off++; 1817 rd_clean_off++;
@@ -1546,6 +1823,38 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1546 have_nick = GNUNET_YES; 1823 have_nick = GNUNET_YES;
1547 } 1824 }
1548 } 1825 }
1826 if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (conv_name,
1827 rd_clean,
1828 rd_clean_off,
1829 rd_nf,
1830 &rd_nf_count,
1831 &new_block_exp,
1832 GNUNET_YES,
1833 &emsg))
1834 {
1835 send_store_response (nc, GNUNET_SYSERR, emsg, rid);
1836 GNUNET_free (emsg);
1837 GNUNET_SERVICE_client_continue (nc->client);
1838 GNUNET_free (conv_name);
1839 return;
1840 }
1841 /*
1842 * If existing_block_exp is 0, then there was not record set
1843 * and no tombstone.
1844 * Otherwise, if the existing block expiration is after the
1845 * new block expiration would be, we need to add a tombstone
1846 * or update it.
1847 */
1848 if (GNUNET_TIME_absolute_cmp (new_block_exp, <=, existing_block_exp))
1849 {
1850 rd_nf[rd_nf_count].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE;
1851 rd_nf[rd_nf_count].expiration_time =
1852 existing_block_exp.abs_value_us;
1853 rd_nf[rd_nf_count].data = NULL;
1854 rd_nf[rd_nf_count].data_size = 0;
1855 rd_nf[rd_nf_count].flags = GNUNET_GNSRECORD_RF_PRIVATE;
1856 rd_nf_count++;
1857 }
1549 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && 1858 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1550 (GNUNET_NO == have_nick)) 1859 (GNUNET_NO == have_nick))
1551 { 1860 {
@@ -1555,19 +1864,18 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1555 res = GSN_database->store_records (GSN_database->cls, 1864 res = GSN_database->store_records (GSN_database->cls,
1556 &rp_msg->private_key, 1865 &rp_msg->private_key,
1557 conv_name, 1866 conv_name,
1558 rd_clean_off, 1867 rd_nf_count,
1559 rd_clean); 1868 rd_nf);
1560 } 1869 }
1561 1870
1562 if (GNUNET_OK != res) 1871 if (GNUNET_OK != res)
1563 { 1872 {
1564 /* store not successful, not need to tell monitors */ 1873 /* store not successful, no need to tell monitors */
1565 send_store_response (nc, res, rid); 1874 send_store_response (nc, res, _ ("Store failed"), rid);
1566 GNUNET_SERVICE_client_continue (nc->client); 1875 GNUNET_SERVICE_client_continue (nc->client);
1567 GNUNET_free (conv_name); 1876 GNUNET_free (conv_name);
1568 return; 1877 return;
1569 } 1878 }
1570
1571 sa = GNUNET_malloc (sizeof(struct StoreActivity) 1879 sa = GNUNET_malloc (sizeof(struct StoreActivity)
1572 + ntohs (rp_msg->gns_header.header.size)); 1880 + ntohs (rp_msg->gns_header.header.size));
1573 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa); 1881 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);