blob: 8f370796f20a07bcd096a34a03ecde83dd64cf2b [file] [log] [blame]
Yingdi Yud04ed1a2013-10-14 14:07:03 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 * Yingdi Yu
5 *
6 * BSD license, See the LICENSE file for more information
7 *
8 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
9 */
10
Yingdi Yu0b0a7362014-08-05 16:31:30 -070011#include "contact-storage.hpp"
Yingdi Yud04ed1a2013-10-14 14:07:03 -070012
Yingdi Yud04ed1a2013-10-14 14:07:03 -070013#include <boost/filesystem.hpp>
Yingdi Yu0b0a7362014-08-05 16:31:30 -070014#include "cryptopp.hpp"
Yingdi Yu3b318c12013-10-15 17:54:00 -070015#include "logging.h"
Yingdi Yud04ed1a2013-10-14 14:07:03 -070016
Yingdi Yu0b0a7362014-08-05 16:31:30 -070017
18// INIT_LOGGER ("chronos.ContactStorage");
19
20namespace chronos {
21
Yingdi Yud04ed1a2013-10-14 14:07:03 -070022namespace fs = boost::filesystem;
23
Yingdi Yu0b0a7362014-08-05 16:31:30 -070024using std::string;
25using std::vector;
Yingdi Yu3b318c12013-10-15 17:54:00 -070026
Yingdi Yu0b0a7362014-08-05 16:31:30 -070027using ndn::PublicKey;
Yingdi Yufa4ce792014-02-06 18:09:22 -080028
Yingdi Yu0b0a7362014-08-05 16:31:30 -070029// user's own profile;
30const string INIT_SP_TABLE =
31 "CREATE TABLE IF NOT EXISTS "
32 " SelfProfile( "
33 " profile_type BLOB NOT NULL, "
34 " profile_value BLOB NOT NULL, "
35 " PRIMARY KEY (profile_type) "
36 " ); "
37 "CREATE INDEX sp_index ON SelfProfile(profile_type); ";
Yingdi Yu17032f82014-03-25 15:48:23 -070038
Yingdi Yu0b0a7362014-08-05 16:31:30 -070039// user's self endorse cert;
40const string INIT_SE_TABLE =
41 "CREATE TABLE IF NOT EXISTS "
42 " SelfEndorse( "
43 " identity BLOB NOT NULL UNIQUE, "
44 " endorse_data BLOB NOT NULL, "
45 " PRIMARY KEY (identity) "
46 " ); "
47 "CREATE INDEX se_index ON SelfEndorse(identity); ";
Yingdi Yu3b318c12013-10-15 17:54:00 -070048
Yingdi Yu0b0a7362014-08-05 16:31:30 -070049// contact's basic info
50const string INIT_CONTACT_TABLE =
51 "CREATE TABLE IF NOT EXISTS "
52 " Contact( "
53 " contact_namespace BLOB NOT NULL, "
54 " contact_alias BLOB NOT NULL, "
55 " contact_keyName BLOB NOT NULL, "
56 " contact_key BLOB NOT NULL, "
57 " notBefore INTEGER DEFAULT 0, "
58 " notAfter INTEGER DEFAULT 0, "
59 " is_introducer INTEGER DEFAULT 0, "
60 " PRIMARY KEY (contact_namespace) "
61 " ); "
62 "CREATE INDEX contact_index ON Contact(contact_namespace); ";
Yingdi Yud04ed1a2013-10-14 14:07:03 -070063
Yingdi Yu0b0a7362014-08-05 16:31:30 -070064// contact's trust scope;
65const string INIT_TS_TABLE =
66 "CREATE TABLE IF NOT EXISTS "
67 " TrustScope( "
68 " id INTEGER PRIMARY KEY AUTOINCREMENT, "
69 " contact_namespace BLOB NOT NULL, "
70 " trust_scope BLOB NOT NULL "
71 " ); "
72 "CREATE INDEX ts_index ON TrustScope(contact_namespace); ";
Yingdi Yud04ed1a2013-10-14 14:07:03 -070073
Yingdi Yu0b0a7362014-08-05 16:31:30 -070074// contact's profile
75const string INIT_CP_TABLE =
76 "CREATE TABLE IF NOT EXISTS "
77 " ContactProfile( "
78 " profile_identity BLOB NOT NULL, "
79 " profile_type BLOB NOT NULL, "
80 " profile_value BLOB NOT NULL, "
81 " endorse INTEGER NOT NULL, "
82 " PRIMARY KEY (profile_identity, profile_type) "
83 " ); "
84 "CREATE INDEX cp_index ON ContactProfile(profile_identity); ";
Yingdi Yub2e747d2013-11-05 23:06:43 -080085
Yingdi Yu0b0a7362014-08-05 16:31:30 -070086// user's endorsement on contacts
87const string INIT_PE_TABLE =
88 "CREATE TABLE IF NOT EXISTS "
89 " ProfileEndorse( "
90 " identity BLOB NOT NULL UNIQUE, "
91 " endorse_data BLOB NOT NULL, "
92 " PRIMARY KEY (identity) "
93 " ); "
94 "CREATE INDEX pe_index ON ProfileEndorse(identity); ";
Yingdi Yub2e747d2013-11-05 23:06:43 -080095
Yingdi Yu0b0a7362014-08-05 16:31:30 -070096// contact's endorsements on the user
97const string INIT_CE_TABLE =
98 "CREATE TABLE IF NOT EXISTS "
99 " CollectEndorse( "
100 " endorser BLOB NOT NULL, "
101 " endorse_name BLOB NOT NULL, "
102 " endorse_data BLOB NOT NULL, "
103 " PRIMARY KEY (endorser) "
104 " ); ";
Yingdi Yub2e747d2013-11-05 23:06:43 -0800105
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700106// dns data;
107const string INIT_DD_TABLE =
108 "CREATE TABLE IF NOT EXISTS "
109 " DnsData( "
110 " dns_name BLOB NOT NULL, "
111 " dns_type BLOB NOT NULL, "
112 " data_name BLOB NOT NULL, "
113 " dns_value BLOB NOT NULL, "
114 " PRIMARY KEY (dns_name, dns_type) "
115 " ); "
116 "CREATE INDEX dd_index ON DnsData(dns_name, dns_type); "
117 "CREATE INDEX dd_index2 ON DnsData(data_name); ";
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700118
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700119/**
120 * A utility function to call the normal sqlite3_bind_text where the value and length are
121 * value.c_str() and value.size().
122 */
123static int
124sqlite3_bind_string(sqlite3_stmt* statement,
125 int index,
126 const string& value,
127 void(*destructor)(void*))
128{
129 return sqlite3_bind_text(statement, index, value.c_str(), value.size(), destructor);
130}
131
132/**
133 * A utility function to call the normal sqlite3_bind_blob where the value and length are
134 * block.wire() and block.size().
135 */
136static int
137sqlite3_bind_block(sqlite3_stmt* statement,
138 int index,
139 const Block& block,
140 void(*destructor)(void*))
141{
142 return sqlite3_bind_blob(statement, index, block.wire(), block.size(), destructor);
143}
144
145/**
146 * A utility function to generate string by calling the normal sqlite3_column_text.
147 */
148static string
149sqlite3_column_string(sqlite3_stmt* statement, int column)
150{
151 return string(reinterpret_cast<const char*>(sqlite3_column_text(statement, column)),
152 sqlite3_column_bytes(statement, column));
153}
154
155/**
156 * A utility function to generate block by calling the normal sqlite3_column_text.
157 */
158static Block
159sqlite3_column_block(sqlite3_stmt* statement, int column)
160{
161 return Block(reinterpret_cast<const char*>(sqlite3_column_blob(statement, column)),
162 sqlite3_column_bytes(statement, column));
163}
164
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800165
166ContactStorage::ContactStorage(const Name& identity)
167 : m_identity(identity)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700168{
169 fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700170 fs::create_directories(chronosDir);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700171
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700172 int res = sqlite3_open((chronosDir / getDBName()).c_str(), &m_db);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700173 if (res != SQLITE_OK)
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800174 throw Error("Chronos DB cannot be open/created");
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700175
Yingdi Yufa4ce792014-02-06 18:09:22 -0800176 initializeTable("SelfProfile", INIT_SP_TABLE);
177 initializeTable("SelfEndorse", INIT_SE_TABLE);
178 initializeTable("Contact", INIT_CONTACT_TABLE);
179 initializeTable("TrustScope", INIT_TS_TABLE);
180 initializeTable("ContactProfile", INIT_CP_TABLE);
181 initializeTable("ProfileEndorse", INIT_PE_TABLE);
182 initializeTable("CollectEndorse", INIT_CE_TABLE);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800183 initializeTable("DnsData", INIT_DD_TABLE);
Yingdi Yu3b318c12013-10-15 17:54:00 -0700184
Yingdi Yu3b318c12013-10-15 17:54:00 -0700185}
186
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700187string
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800188ContactStorage::getDBName()
189{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700190 string dbName("chronos-");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800191
Yingdi Yu17032f82014-03-25 15:48:23 -0700192 std::stringstream ss;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800193 {
194 using namespace CryptoPP;
195
196 SHA256 hash;
197 StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
198 new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
199 }
200 dbName.append(ss.str()).append(".db");
201
202 return dbName;
203}
204
Yingdi Yu3b318c12013-10-15 17:54:00 -0700205void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700206ContactStorage::initializeTable(const string& tableName, const string& sqlCreateStmt)
Yingdi Yu3b318c12013-10-15 17:54:00 -0700207{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800208 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700209 sqlite3_prepare_v2(m_db,
210 "SELECT name FROM sqlite_master WHERE type='table' And name=?",
211 -1, &stmt, 0);
212 sqlite3_bind_string(stmt, 1, tableName, SQLITE_TRANSIENT);
213 int res = sqlite3_step(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800214
215 bool tableExist = false;
216 if (res == SQLITE_ROW)
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700217 tableExist = true;
218 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800219
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700220 if (!tableExist) {
221 char *errmsg = 0;
222 res = sqlite3_exec(m_db, sqlCreateStmt.c_str (), NULL, NULL, &errmsg);
223 if (res != SQLITE_OK && errmsg != 0)
224 throw Error("Init \"error\" in " + tableName);
225 }
Yingdi Yu3b318c12013-10-15 17:54:00 -0700226}
227
Yingdi Yu76dd8002013-12-24 11:16:32 +0800228shared_ptr<Profile>
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800229ContactStorage::getSelfProfile()
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700230{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800231 shared_ptr<Profile> profile = make_shared<Profile>(m_identity);
Yingdi Yu3b318c12013-10-15 17:54:00 -0700232 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700233 sqlite3_prepare_v2(m_db, "SELECT profile_type, profile_value FROM SelfProfile", -1, &stmt, 0);
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700234
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700235 while (sqlite3_step(stmt) == SQLITE_ROW) {
236 string profileType = sqlite3_column_string(stmt, 0);
237 string profileValue = sqlite3_column_string (stmt, 1);
238 (*profile)[profileType] = profileValue;
239 }
Yingdi Yu72781e52013-11-06 23:00:21 -0800240 sqlite3_finalize(stmt);
241
Yingdi Yu3b318c12013-10-15 17:54:00 -0700242 return profile;
243}
Yingdi Yuae8217c2013-11-09 00:03:26 -0800244
Yingdi Yufa4ce792014-02-06 18:09:22 -0800245void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800246ContactStorage::addSelfEndorseCertificate(const EndorseCertificate& newEndorseCertificate)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800247{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800248 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700249 sqlite3_prepare_v2(m_db,
250 "INSERT OR REPLACE INTO SelfEndorse (identity, endorse_data) values (?, ?)",
251 -1, &stmt, 0);
252 sqlite3_bind_string(stmt, 1, m_identity.toUri(), SQLITE_TRANSIENT);
253 sqlite3_bind_block(stmt, 2, newEndorseCertificate.wireEncode(), SQLITE_TRANSIENT);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800254 int res = sqlite3_step(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800255
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700256 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800257}
258
Yingdi Yufa4ce792014-02-06 18:09:22 -0800259void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700260ContactStorage::addEndorseCertificate(const EndorseCertificate& endorseCertificate,
261 const Name& identity)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800262{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800263 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700264 sqlite3_prepare_v2(m_db,
265 "INSERT OR REPLACE INTO ProfileEndorse \
266 (identity, endorse_data) values (?, ?)",
267 -1, &stmt, 0);
268 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
269 sqlite3_bind_block(stmt, 2, endorseCertificate.wireEncode(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800270 sqlite3_step(stmt);
271
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700272 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800273}
274
275void
276ContactStorage::updateCollectEndorse(const EndorseCertificate& endorseCertificate)
277{
278 Name endorserName = endorseCertificate.getSigner();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800279 Name certName = endorseCertificate.getName();
Yingdi Yufa4ce792014-02-06 18:09:22 -0800280
281 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700282 sqlite3_prepare_v2(m_db,
283 "INSERT OR REPLACE INTO CollectEndorse \
284 (endorser, endorse_name, endorse_data) \
285 VALUES (?, ?, ?, ?)",
286 -1, &stmt, 0);
287 sqlite3_bind_string(stmt, 1, endorserName.toUri(), SQLITE_TRANSIENT);
288 sqlite3_bind_string(stmt, 2, certName.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800289 const Block &block = endorseCertificate.wireEncode();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700290 sqlite3_bind_block(stmt, 3, endorseCertificate.wireEncode(), SQLITE_TRANSIENT);
291 int res = sqlite3_step(stmt);
292 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800293 return;
294}
295
296void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800297ContactStorage::getCollectEndorse(EndorseCollection& endorseCollection)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800298{
299 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700300 sqlite3_prepare_v2(m_db, "SELECT endorse_name, endorse_data FROM CollectEndorse", -1, &stmt, 0);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800301
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700302 while (sqlite3_step(stmt) == SQLITE_ROW) {
303 string certName = sqlite3_column_string(stmt, 0);
304 std::stringstream ss;
Yingdi Yufa4ce792014-02-06 18:09:22 -0800305 {
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700306 using namespace CryptoPP;
307 SHA256 hash;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800308
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700309 StringSource(sqlite3_column_text(stmt, 1), sqlite3_column_bytes (stmt, 1), true,
310 new HashFilter(hash, new FileSink(ss)));
Yingdi Yufa4ce792014-02-06 18:09:22 -0800311 }
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700312 EndorseCollection::Endorsement* endorsement = endorseCollection.add_endorsement();
313 endorsement->set_certname(certName);
314 endorsement->set_hash(ss.str());
315 }
Yingdi Yufa4ce792014-02-06 18:09:22 -0800316
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700317 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800318}
319
320void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700321ContactStorage::getEndorseList(const Name& identity, vector<string>& endorseList)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800322{
323 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700324 sqlite3_prepare_v2(m_db,
325 "SELECT profile_type FROM ContactProfile \
326 WHERE profile_identity=? AND endorse=1 ORDER BY profile_type",
327 -1, &stmt, 0);
328 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800329
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700330 while (sqlite3_step(stmt) == SQLITE_ROW) {
331 string profileType = sqlite3_column_string(stmt, 0);
332 endorseList.push_back(profileType);
333 }
334 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800335}
336
337
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700338void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800339ContactStorage::removeContact(const Name& identityName)
Yingdi Yuae8217c2013-11-09 00:03:26 -0800340{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700341 string identity = identityName.toUri();
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700342
343 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700344 sqlite3_prepare_v2(m_db, "DELETE FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
345 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
346 int res = sqlite3_step(stmt);
347 sqlite3_finalize(stmt);
Yingdi Yuae8217c2013-11-09 00:03:26 -0800348
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700349 sqlite3_prepare_v2(m_db, "DELETE FROM ContactProfile WHERE profile_identity=?", -1, &stmt, 0);
350 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
351 res = sqlite3_step(stmt);
352 sqlite3_finalize(stmt);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700353
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700354 sqlite3_prepare_v2(m_db, "DELETE FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
355 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
356 res = sqlite3_step(stmt);
357 sqlite3_finalize(stmt);
Yingdi Yuae8217c2013-11-09 00:03:26 -0800358}
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700359
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700360void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800361ContactStorage::addContact(const Contact& contact)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700362{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700363 if (doesContactExist(contact.getNameSpace()))
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800364 throw Error("Normal Contact has already existed");
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700365
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700366 string identity = contact.getNameSpace().toUri();
Yingdi Yu71c01872013-11-03 16:22:05 -0800367 bool isIntroducer = contact.isIntroducer();
368
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700369 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700370 sqlite3_prepare_v2(m_db,
371 "INSERT INTO Contact (contact_namespace, contact_alias, contact_keyName, \
372 contact_key, notBefore, notAfter, is_introducer) \
373 values (?, ?, ?, ?, ?, ?, ?)",
374 -1, &stmt, 0);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700375
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700376 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
377 sqlite3_bind_string(stmt, 2, contact.getAlias(), SQLITE_TRANSIENT);
378 sqlite3_bind_string(stmt, 3, contact.getPublicKeyName().toUri(), SQLITE_TRANSIENT);
379 sqlite3_bind_text(stmt, 4,
380 reinterpret_cast<const char*>(contact.getPublicKey().get().buf()),
381 contact.getPublicKey().get().size(), SQLITE_TRANSIENT);
Yingdi Yua7876722014-03-25 14:46:55 -0700382 sqlite3_bind_int64(stmt, 5, time::toUnixTimestamp(contact.getNotBefore()).count());
383 sqlite3_bind_int64(stmt, 6, time::toUnixTimestamp(contact.getNotAfter()).count());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800384 sqlite3_bind_int(stmt, 7, (isIntroducer ? 1 : 0));
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700385
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700386 int res = sqlite3_step(stmt);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800387
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700388 sqlite3_finalize(stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800389
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800390 const Profile& profile = contact.getProfile();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700391 for (Profile::const_iterator it = profile.begin(); it != profile.end(); it++) {
392 sqlite3_prepare_v2(m_db,
393 "INSERT INTO ContactProfile \
394 (profile_identity, profile_type, profile_value, endorse) \
395 values (?, ?, ?, 0)",
396 -1, &stmt, 0);
397 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
398 sqlite3_bind_string(stmt, 2, it->first, SQLITE_TRANSIENT);
399 sqlite3_bind_string(stmt, 3, it->second, SQLITE_TRANSIENT);
400 res = sqlite3_step(stmt);
401 sqlite3_finalize(stmt);
402 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800403
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700404 if (isIntroducer) {
405 Contact::const_iterator it = contact.trustScopeBegin();
406 Contact::const_iterator end = contact.trustScopeEnd();
407
408 while (it != end) {
409 sqlite3_prepare_v2(m_db,
410 "INSERT INTO TrustScope (contact_namespace, trust_scope) values (?, ?)",
411 -1, &stmt, 0);
412 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
413 sqlite3_bind_string(stmt, 2, it->first.toUri(), SQLITE_TRANSIENT);
414 res = sqlite3_step(stmt);
415 sqlite3_finalize(stmt);
416 it++;
Yingdi Yub2e747d2013-11-05 23:06:43 -0800417 }
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700418 }
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700419}
420
Yingdi Yufa4ce792014-02-06 18:09:22 -0800421
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800422shared_ptr<Contact>
423ContactStorage::getContact(const Name& identity) const
Yingdi Yufa4ce792014-02-06 18:09:22 -0800424{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800425 shared_ptr<Contact> contact;
426 Profile profile;
427
Yingdi Yufa4ce792014-02-06 18:09:22 -0800428 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700429 sqlite3_prepare_v2(m_db,
430 "SELECT contact_alias, contact_keyName, contact_key, notBefore, notAfter, \
431 is_introducer FROM Contact where contact_namespace=?",
432 -1, &stmt, 0);
433 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800434
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700435 if (sqlite3_step(stmt) == SQLITE_ROW) {
436 string alias = sqlite3_column_string(stmt, 0);
437 string keyName = sqlite3_column_string(stmt, 1);
438 PublicKey key(sqlite3_column_text(stmt, 2), sqlite3_column_bytes (stmt, 2));
439 time::system_clock::TimePoint notBefore =
440 time::fromUnixTimestamp(time::milliseconds(sqlite3_column_int64 (stmt, 3)));
441 time::system_clock::TimePoint notAfter =
442 time::fromUnixTimestamp(time::milliseconds(sqlite3_column_int64 (stmt, 4)));
443 int isIntroducer = sqlite3_column_int (stmt, 5);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800444
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700445 contact = make_shared<Contact>(identity, alias, Name(keyName),
446 notBefore, notAfter, key, isIntroducer);
447 }
448 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800449
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700450 sqlite3_prepare_v2(m_db,
451 "SELECT profile_type, profile_value FROM ContactProfile \
452 where profile_identity=?",
453 -1, &stmt, 0);
454 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700455
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700456 while (sqlite3_step(stmt) == SQLITE_ROW) {
457 string type = sqlite3_column_string(stmt, 0);
458 string value = sqlite3_column_string(stmt, 1);
459 profile[type] = value;
460 }
461 sqlite3_finalize(stmt);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800462 contact->setProfile(profile);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800463
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700464 if (contact->isIntroducer()) {
465 sqlite3_prepare_v2(m_db,
466 "SELECT trust_scope FROM TrustScope WHERE contact_namespace=?",
467 -1, &stmt, 0);
468 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800469
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700470 while (sqlite3_step(stmt) == SQLITE_ROW) {
471 Name scope(sqlite3_column_string(stmt, 0));
472 contact->addTrustScope(scope);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800473 }
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700474 sqlite3_finalize(stmt);
475 }
Yingdi Yufa4ce792014-02-06 18:09:22 -0800476
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800477 return contact;
Yingdi Yufa4ce792014-02-06 18:09:22 -0800478}
479
480
Yingdi Yub2e747d2013-11-05 23:06:43 -0800481void
Yingdi Yufa4ce792014-02-06 18:09:22 -0800482ContactStorage::updateIsIntroducer(const Name& identity, bool isIntroducer)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800483{
484 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700485 sqlite3_prepare_v2(m_db, "UPDATE Contact SET is_introducer=? WHERE contact_namespace=?",
486 -1, &stmt, 0);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800487 sqlite3_bind_int(stmt, 1, (isIntroducer ? 1 : 0));
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700488 sqlite3_bind_string(stmt, 2, identity.toUri(), SQLITE_TRANSIENT);
489 int res = sqlite3_step(stmt);
490 sqlite3_finalize(stmt);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800491 return;
492}
493
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700494void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700495ContactStorage::updateAlias(const Name& identity, const string& alias)
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700496{
Yingdi Yu71c01872013-11-03 16:22:05 -0800497 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700498 sqlite3_prepare_v2(m_db, "UPDATE Contact SET contact_alias=? WHERE contact_namespace=?",
499 -1, &stmt, 0);
500 sqlite3_bind_string(stmt, 1, alias, SQLITE_TRANSIENT);
501 sqlite3_bind_string(stmt, 2, identity.toUri(), SQLITE_TRANSIENT);
502 int res = sqlite3_step(stmt);
503 sqlite3_finalize(stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800504 return;
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700505}
506
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700507bool
Yingdi Yu71c01872013-11-03 16:22:05 -0800508ContactStorage::doesContactExist(const Name& name)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700509{
510 bool result = false;
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700511
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700512 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700513 sqlite3_prepare_v2(m_db, "SELECT count(*) FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
514 sqlite3_bind_string(stmt, 1, name.toUri(), SQLITE_TRANSIENT);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700515
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700516 int res = sqlite3_step(stmt);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700517
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700518 if (res == SQLITE_ROW) {
519 int countAll = sqlite3_column_int (stmt, 0);
520 if (countAll > 0)
521 result = true;
522 }
523
524 sqlite3_finalize(stmt);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700525 return result;
526}
527
Yingdi Yu76dd8002013-12-24 11:16:32 +0800528void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700529ContactStorage::getAllContacts(vector<shared_ptr<Contact> >& contacts) const
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700530{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700531 vector<Name> contactNames;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800532
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700533 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700534 sqlite3_prepare_v2(m_db, "SELECT contact_namespace FROM Contact", -1, &stmt, 0);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700535
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700536 while (sqlite3_step(stmt) == SQLITE_ROW) {
537 string identity = sqlite3_column_string(stmt, 0);
538 contactNames.push_back(Name(identity));
539 }
540 sqlite3_finalize(stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800541
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700542 for (vector<Name>::iterator it = contactNames.begin(); it != contactNames.end(); it++) {
543 shared_ptr<Contact> contact = getContact(*it);
544 if (static_cast<bool>(contact))
545 contacts.push_back(contact);
546 }
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700547}
Yingdi Yu3b318c12013-10-15 17:54:00 -0700548
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800549void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700550ContactStorage::updateDnsData(const Block& data, const string& name,
551 const string& type, const string& dataName)
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700552{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800553 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700554 sqlite3_prepare_v2(m_db,
555 "INSERT OR REPLACE INTO DnsData (dns_name, dns_type, dns_value, data_name) \
556 VALUES (?, ?, ?, ?)",
557 -1, &stmt, 0);
558 sqlite3_bind_string(stmt, 1, name, SQLITE_TRANSIENT);
559 sqlite3_bind_string(stmt, 2, type, SQLITE_TRANSIENT);
560 sqlite3_bind_block(stmt, 3, data, SQLITE_TRANSIENT);
561 sqlite3_bind_string(stmt, 4, dataName, SQLITE_TRANSIENT);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800562 int res = sqlite3_step(stmt);
563
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800564 sqlite3_finalize(stmt);
565}
566
567shared_ptr<Data>
568ContactStorage::getDnsData(const Name& dataName)
569{
570 shared_ptr<Data> data;
571
572 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700573 sqlite3_prepare_v2(m_db, "SELECT dns_value FROM DnsData where data_name=?", -1, &stmt, 0);
574 sqlite3_bind_string(stmt, 1, dataName.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700575
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700576 if (sqlite3_step(stmt) == SQLITE_ROW) {
577 data = make_shared<Data>();
578 data->wireDecode(sqlite3_column_block(stmt, 0));
579 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800580 sqlite3_finalize(stmt);
581
582 return data;
583}
584
585shared_ptr<Data>
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700586ContactStorage::getDnsData(const string& name, const string& type)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800587{
588 shared_ptr<Data> data;
589
590 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700591 sqlite3_prepare_v2(m_db, "SELECT dns_value FROM DnsData where dns_name=? and dns_type=?",
592 -1, &stmt, 0);
593 sqlite3_bind_string(stmt, 1, name, SQLITE_TRANSIENT);
594 sqlite3_bind_string(stmt, 2, type, SQLITE_TRANSIENT);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700595
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700596 if (sqlite3_step(stmt) == SQLITE_ROW) {
597 data = make_shared<Data>();
598 data->wireDecode(sqlite3_column_block(stmt, 0));
599 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800600 sqlite3_finalize(stmt);
601
602 return data;
603}
604
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700605} // namespace chronos