blob: d5e0fe22fef0eaa839baa293487df42da785ce22 [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>
Qiuhan Ding0cfc1512015-02-17 17:44:11 -08009 * Author: Qiuhan Ding <qiuhanding@cs.ucla.edu>
Yingdi Yud04ed1a2013-10-14 14:07:03 -070010 */
11
Yingdi Yu0b0a7362014-08-05 16:31:30 -070012#include "contact-storage.hpp"
Yingdi Yud04ed1a2013-10-14 14:07:03 -070013
Yingdi Yud04ed1a2013-10-14 14:07:03 -070014#include <boost/filesystem.hpp>
Yingdi Yu0b0a7362014-08-05 16:31:30 -070015#include "cryptopp.hpp"
Yingdi Yud04ed1a2013-10-14 14:07:03 -070016
Yingdi Yu0b0a7362014-08-05 16:31:30 -070017
Yingdi Yueb692ac2015-02-10 18:46:18 -080018namespace chronochat {
Yingdi Yu0b0a7362014-08-05 16:31:30 -070019
Yingdi Yud04ed1a2013-10-14 14:07:03 -070020namespace fs = boost::filesystem;
21
Yingdi Yu0b0a7362014-08-05 16:31:30 -070022using std::string;
23using std::vector;
Yingdi Yu3b318c12013-10-15 17:54:00 -070024
Yingdi Yu0b0a7362014-08-05 16:31:30 -070025// user's own profile;
26const string INIT_SP_TABLE =
27 "CREATE TABLE IF NOT EXISTS "
28 " SelfProfile( "
29 " profile_type BLOB NOT NULL, "
30 " profile_value BLOB NOT NULL, "
31 " PRIMARY KEY (profile_type) "
32 " ); "
33 "CREATE INDEX sp_index ON SelfProfile(profile_type); ";
Yingdi Yu17032f82014-03-25 15:48:23 -070034
Yingdi Yu0b0a7362014-08-05 16:31:30 -070035// user's self endorse cert;
36const string INIT_SE_TABLE =
37 "CREATE TABLE IF NOT EXISTS "
38 " SelfEndorse( "
39 " identity BLOB NOT NULL UNIQUE, "
40 " endorse_data BLOB NOT NULL, "
41 " PRIMARY KEY (identity) "
42 " ); "
43 "CREATE INDEX se_index ON SelfEndorse(identity); ";
Yingdi Yu3b318c12013-10-15 17:54:00 -070044
Yingdi Yu0b0a7362014-08-05 16:31:30 -070045// contact's basic info
46const string INIT_CONTACT_TABLE =
47 "CREATE TABLE IF NOT EXISTS "
48 " Contact( "
49 " contact_namespace BLOB NOT NULL, "
50 " contact_alias BLOB NOT NULL, "
51 " contact_keyName BLOB NOT NULL, "
52 " contact_key BLOB NOT NULL, "
53 " notBefore INTEGER DEFAULT 0, "
54 " notAfter INTEGER DEFAULT 0, "
55 " is_introducer INTEGER DEFAULT 0, "
56 " PRIMARY KEY (contact_namespace) "
57 " ); "
58 "CREATE INDEX contact_index ON Contact(contact_namespace); ";
Yingdi Yud04ed1a2013-10-14 14:07:03 -070059
Yingdi Yu0b0a7362014-08-05 16:31:30 -070060// contact's trust scope;
61const string INIT_TS_TABLE =
62 "CREATE TABLE IF NOT EXISTS "
63 " TrustScope( "
64 " id INTEGER PRIMARY KEY AUTOINCREMENT, "
65 " contact_namespace BLOB NOT NULL, "
66 " trust_scope BLOB NOT NULL "
67 " ); "
68 "CREATE INDEX ts_index ON TrustScope(contact_namespace); ";
Yingdi Yud04ed1a2013-10-14 14:07:03 -070069
Yingdi Yu0b0a7362014-08-05 16:31:30 -070070// contact's profile
71const string INIT_CP_TABLE =
72 "CREATE TABLE IF NOT EXISTS "
73 " ContactProfile( "
74 " profile_identity BLOB NOT NULL, "
75 " profile_type BLOB NOT NULL, "
76 " profile_value BLOB NOT NULL, "
77 " endorse INTEGER NOT NULL, "
78 " PRIMARY KEY (profile_identity, profile_type) "
79 " ); "
80 "CREATE INDEX cp_index ON ContactProfile(profile_identity); ";
Yingdi Yub2e747d2013-11-05 23:06:43 -080081
Yingdi Yu0b0a7362014-08-05 16:31:30 -070082// user's endorsement on contacts
83const string INIT_PE_TABLE =
84 "CREATE TABLE IF NOT EXISTS "
85 " ProfileEndorse( "
86 " identity BLOB NOT NULL UNIQUE, "
87 " endorse_data BLOB NOT NULL, "
88 " PRIMARY KEY (identity) "
89 " ); "
90 "CREATE INDEX pe_index ON ProfileEndorse(identity); ";
Yingdi Yub2e747d2013-11-05 23:06:43 -080091
Yingdi Yu0b0a7362014-08-05 16:31:30 -070092// contact's endorsements on the user
93const string INIT_CE_TABLE =
94 "CREATE TABLE IF NOT EXISTS "
95 " CollectEndorse( "
96 " endorser BLOB NOT NULL, "
97 " endorse_name BLOB NOT NULL, "
98 " endorse_data BLOB NOT NULL, "
99 " PRIMARY KEY (endorser) "
100 " ); ";
Yingdi Yub2e747d2013-11-05 23:06:43 -0800101
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700102// dns data;
103const string INIT_DD_TABLE =
104 "CREATE TABLE IF NOT EXISTS "
105 " DnsData( "
106 " dns_name BLOB NOT NULL, "
107 " dns_type BLOB NOT NULL, "
108 " data_name BLOB NOT NULL, "
109 " dns_value BLOB NOT NULL, "
110 " PRIMARY KEY (dns_name, dns_type) "
111 " ); "
112 "CREATE INDEX dd_index ON DnsData(dns_name, dns_type); "
113 "CREATE INDEX dd_index2 ON DnsData(data_name); ";
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700114
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700115/**
116 * A utility function to call the normal sqlite3_bind_text where the value and length are
117 * value.c_str() and value.size().
118 */
119static int
120sqlite3_bind_string(sqlite3_stmt* statement,
121 int index,
122 const string& value,
123 void(*destructor)(void*))
124{
125 return sqlite3_bind_text(statement, index, value.c_str(), value.size(), destructor);
126}
127
128/**
129 * A utility function to call the normal sqlite3_bind_blob where the value and length are
130 * block.wire() and block.size().
131 */
132static int
133sqlite3_bind_block(sqlite3_stmt* statement,
134 int index,
135 const Block& block,
136 void(*destructor)(void*))
137{
138 return sqlite3_bind_blob(statement, index, block.wire(), block.size(), destructor);
139}
140
141/**
142 * A utility function to generate string by calling the normal sqlite3_column_text.
143 */
144static string
145sqlite3_column_string(sqlite3_stmt* statement, int column)
146{
147 return string(reinterpret_cast<const char*>(sqlite3_column_text(statement, column)),
148 sqlite3_column_bytes(statement, column));
149}
150
151/**
152 * A utility function to generate block by calling the normal sqlite3_column_text.
153 */
154static Block
155sqlite3_column_block(sqlite3_stmt* statement, int column)
156{
Varun Patil3d850902020-11-23 12:19:14 +0530157 return Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(statement, column)),
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700158 sqlite3_column_bytes(statement, column));
159}
160
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800161
162ContactStorage::ContactStorage(const Name& identity)
163 : m_identity(identity)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700164{
165 fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700166 fs::create_directories(chronosDir);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700167
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700168 int res = sqlite3_open((chronosDir / getDBName()).c_str(), &m_db);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700169 if (res != SQLITE_OK)
Yingdi Yueb692ac2015-02-10 18:46:18 -0800170 throw Error("chronochat DB cannot be open/created");
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700171
Yingdi Yufa4ce792014-02-06 18:09:22 -0800172 initializeTable("SelfProfile", INIT_SP_TABLE);
173 initializeTable("SelfEndorse", INIT_SE_TABLE);
174 initializeTable("Contact", INIT_CONTACT_TABLE);
175 initializeTable("TrustScope", INIT_TS_TABLE);
176 initializeTable("ContactProfile", INIT_CP_TABLE);
177 initializeTable("ProfileEndorse", INIT_PE_TABLE);
178 initializeTable("CollectEndorse", INIT_CE_TABLE);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800179 initializeTable("DnsData", INIT_DD_TABLE);
Yingdi Yu3b318c12013-10-15 17:54:00 -0700180
Yingdi Yu3b318c12013-10-15 17:54:00 -0700181}
182
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700183string
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800184ContactStorage::getDBName()
185{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700186 string dbName("chronos-");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800187
Yingdi Yu17032f82014-03-25 15:48:23 -0700188 std::stringstream ss;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800189 {
190 using namespace CryptoPP;
191
192 SHA256 hash;
193 StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
194 new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
195 }
196 dbName.append(ss.str()).append(".db");
197
198 return dbName;
199}
200
Yingdi Yu3b318c12013-10-15 17:54:00 -0700201void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700202ContactStorage::initializeTable(const string& tableName, const string& sqlCreateStmt)
Yingdi Yu3b318c12013-10-15 17:54:00 -0700203{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800204 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700205 sqlite3_prepare_v2(m_db,
206 "SELECT name FROM sqlite_master WHERE type='table' And name=?",
207 -1, &stmt, 0);
208 sqlite3_bind_string(stmt, 1, tableName, SQLITE_TRANSIENT);
209 int res = sqlite3_step(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800210
211 bool tableExist = false;
212 if (res == SQLITE_ROW)
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700213 tableExist = true;
214 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800215
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700216 if (!tableExist) {
217 char *errmsg = 0;
218 res = sqlite3_exec(m_db, sqlCreateStmt.c_str (), NULL, NULL, &errmsg);
219 if (res != SQLITE_OK && errmsg != 0)
220 throw Error("Init \"error\" in " + tableName);
221 }
Yingdi Yu3b318c12013-10-15 17:54:00 -0700222}
223
Yingdi Yu76dd8002013-12-24 11:16:32 +0800224shared_ptr<Profile>
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800225ContactStorage::getSelfProfile()
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700226{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800227 shared_ptr<Profile> profile = make_shared<Profile>(m_identity);
Yingdi Yu3b318c12013-10-15 17:54:00 -0700228 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700229 sqlite3_prepare_v2(m_db, "SELECT profile_type, profile_value FROM SelfProfile", -1, &stmt, 0);
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700230
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700231 while (sqlite3_step(stmt) == SQLITE_ROW) {
232 string profileType = sqlite3_column_string(stmt, 0);
233 string profileValue = sqlite3_column_string (stmt, 1);
234 (*profile)[profileType] = profileValue;
235 }
Yingdi Yu72781e52013-11-06 23:00:21 -0800236 sqlite3_finalize(stmt);
237
Yingdi Yu3b318c12013-10-15 17:54:00 -0700238 return profile;
239}
Yingdi Yuae8217c2013-11-09 00:03:26 -0800240
Yingdi Yufa4ce792014-02-06 18:09:22 -0800241void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800242ContactStorage::addSelfEndorseCertificate(const EndorseCertificate& newEndorseCertificate)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800243{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800244 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700245 sqlite3_prepare_v2(m_db,
246 "INSERT OR REPLACE INTO SelfEndorse (identity, endorse_data) values (?, ?)",
247 -1, &stmt, 0);
248 sqlite3_bind_string(stmt, 1, m_identity.toUri(), SQLITE_TRANSIENT);
249 sqlite3_bind_block(stmt, 2, newEndorseCertificate.wireEncode(), SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700250 sqlite3_step(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800251
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700252 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800253}
254
Varun Patil3d850902020-11-23 12:19:14 +0530255shared_ptr<EndorseCertificate>
256ContactStorage::getSelfEndorseCertificate()
257{
258 shared_ptr<EndorseCertificate> cert;
259
260 sqlite3_stmt *stmt;
261 sqlite3_prepare_v2(m_db,
262 "SELECT endorse_data FROM SelfEndorse where identity=?",
263 -1, &stmt, 0);
264 sqlite3_bind_string(stmt, 1, m_identity.toUri(), SQLITE_TRANSIENT);
265
266 if (sqlite3_step(stmt) == SQLITE_ROW) {
267 cert = make_shared<EndorseCertificate>();
268 cert->wireDecode(sqlite3_column_block(stmt, 0));
269 }
270
271 sqlite3_finalize(stmt);
272
273 return cert;
274}
275
Yingdi Yufa4ce792014-02-06 18:09:22 -0800276void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700277ContactStorage::addEndorseCertificate(const EndorseCertificate& endorseCertificate,
278 const Name& identity)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800279{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800280 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700281 sqlite3_prepare_v2(m_db,
282 "INSERT OR REPLACE INTO ProfileEndorse \
283 (identity, endorse_data) values (?, ?)",
284 -1, &stmt, 0);
285 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
286 sqlite3_bind_block(stmt, 2, endorseCertificate.wireEncode(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800287 sqlite3_step(stmt);
288
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700289 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800290}
291
292void
293ContactStorage::updateCollectEndorse(const EndorseCertificate& endorseCertificate)
294{
295 Name endorserName = endorseCertificate.getSigner();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800296 Name certName = endorseCertificate.getName();
Yingdi Yufa4ce792014-02-06 18:09:22 -0800297
298 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700299 sqlite3_prepare_v2(m_db,
300 "INSERT OR REPLACE INTO CollectEndorse \
301 (endorser, endorse_name, endorse_data) \
Varun Patil3d850902020-11-23 12:19:14 +0530302 VALUES (?, ?, ?)",
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700303 -1, &stmt, 0);
304 sqlite3_bind_string(stmt, 1, endorserName.toUri(), SQLITE_TRANSIENT);
305 sqlite3_bind_string(stmt, 2, certName.toUri(), SQLITE_TRANSIENT);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700306 sqlite3_bind_block(stmt, 3, endorseCertificate.wireEncode(), SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700307 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700308 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800309 return;
310}
311
312void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800313ContactStorage::getCollectEndorse(EndorseCollection& endorseCollection)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800314{
315 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700316 sqlite3_prepare_v2(m_db, "SELECT endorse_name, endorse_data FROM CollectEndorse", -1, &stmt, 0);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800317
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700318 while (sqlite3_step(stmt) == SQLITE_ROW) {
319 string certName = sqlite3_column_string(stmt, 0);
320 std::stringstream ss;
Yingdi Yufa4ce792014-02-06 18:09:22 -0800321 {
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700322 using namespace CryptoPP;
323 SHA256 hash;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800324
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700325 StringSource(sqlite3_column_text(stmt, 1), sqlite3_column_bytes (stmt, 1), true,
326 new HashFilter(hash, new FileSink(ss)));
Yingdi Yufa4ce792014-02-06 18:09:22 -0800327 }
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800328 endorseCollection.addCollectionEntry(Name(certName), ss.str());
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700329 }
Yingdi Yufa4ce792014-02-06 18:09:22 -0800330
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700331 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800332}
333
Varun Patil3d850902020-11-23 12:19:14 +0530334shared_ptr<EndorseCertificate>
335ContactStorage::getCollectEndorseByName(const Name& name)
336{
337 shared_ptr<EndorseCertificate> cert;
338
339 sqlite3_stmt *stmt;
340 sqlite3_prepare_v2(m_db,
341 "SELECT endorse_name, endorse_data FROM CollectEndorse where endorse_name=?",
342 -1, &stmt, 0);
343 sqlite3_bind_string(stmt, 1, name.toUri(), SQLITE_TRANSIENT);
344
345 if (sqlite3_step(stmt) == SQLITE_ROW) {
346 cert = make_shared<EndorseCertificate>();
347 cert->wireDecode(sqlite3_column_block(stmt, 1));
348 }
349
350 sqlite3_finalize(stmt);
351
352 return cert;
353}
354
Yingdi Yufa4ce792014-02-06 18:09:22 -0800355void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700356ContactStorage::getEndorseList(const Name& identity, vector<string>& endorseList)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800357{
358 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700359 sqlite3_prepare_v2(m_db,
360 "SELECT profile_type FROM ContactProfile \
361 WHERE profile_identity=? AND endorse=1 ORDER BY profile_type",
362 -1, &stmt, 0);
363 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800364
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700365 while (sqlite3_step(stmt) == SQLITE_ROW) {
366 string profileType = sqlite3_column_string(stmt, 0);
367 endorseList.push_back(profileType);
368 }
369 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800370}
371
372
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700373void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800374ContactStorage::removeContact(const Name& identityName)
Yingdi Yuae8217c2013-11-09 00:03:26 -0800375{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700376 string identity = identityName.toUri();
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700377
378 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700379 sqlite3_prepare_v2(m_db, "DELETE FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
380 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700381 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700382 sqlite3_finalize(stmt);
Yingdi Yuae8217c2013-11-09 00:03:26 -0800383
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700384 sqlite3_prepare_v2(m_db, "DELETE FROM ContactProfile WHERE profile_identity=?", -1, &stmt, 0);
385 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700386 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700387 sqlite3_finalize(stmt);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700388
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700389 sqlite3_prepare_v2(m_db, "DELETE FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
390 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700391 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700392 sqlite3_finalize(stmt);
Yingdi Yuae8217c2013-11-09 00:03:26 -0800393}
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700394
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700395void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800396ContactStorage::addContact(const Contact& contact)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700397{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700398 if (doesContactExist(contact.getNameSpace()))
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800399 throw Error("Normal Contact has already existed");
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700400
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700401 string identity = contact.getNameSpace().toUri();
Yingdi Yu71c01872013-11-03 16:22:05 -0800402 bool isIntroducer = contact.isIntroducer();
403
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700404 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700405 sqlite3_prepare_v2(m_db,
406 "INSERT INTO Contact (contact_namespace, contact_alias, contact_keyName, \
407 contact_key, notBefore, notAfter, is_introducer) \
408 values (?, ?, ?, ?, ?, ?, ?)",
409 -1, &stmt, 0);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700410
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700411 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
412 sqlite3_bind_string(stmt, 2, contact.getAlias(), SQLITE_TRANSIENT);
413 sqlite3_bind_string(stmt, 3, contact.getPublicKeyName().toUri(), SQLITE_TRANSIENT);
414 sqlite3_bind_text(stmt, 4,
Varun Patil3d850902020-11-23 12:19:14 +0530415 reinterpret_cast<const char*>(contact.getPublicKey().data()),
416 contact.getPublicKey().size(), SQLITE_TRANSIENT);
Yingdi Yua7876722014-03-25 14:46:55 -0700417 sqlite3_bind_int64(stmt, 5, time::toUnixTimestamp(contact.getNotBefore()).count());
418 sqlite3_bind_int64(stmt, 6, time::toUnixTimestamp(contact.getNotAfter()).count());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800419 sqlite3_bind_int(stmt, 7, (isIntroducer ? 1 : 0));
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700420
Yingdi Yu1cc45d92015-02-09 14:19:54 -0800421 sqlite3_step(stmt);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800422
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700423 sqlite3_finalize(stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800424
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800425 const Profile& profile = contact.getProfile();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700426 for (Profile::const_iterator it = profile.begin(); it != profile.end(); it++) {
427 sqlite3_prepare_v2(m_db,
428 "INSERT INTO ContactProfile \
429 (profile_identity, profile_type, profile_value, endorse) \
430 values (?, ?, ?, 0)",
431 -1, &stmt, 0);
432 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
433 sqlite3_bind_string(stmt, 2, it->first, SQLITE_TRANSIENT);
434 sqlite3_bind_string(stmt, 3, it->second, SQLITE_TRANSIENT);
Yingdi Yu1cc45d92015-02-09 14:19:54 -0800435 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700436 sqlite3_finalize(stmt);
437 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800438
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700439 if (isIntroducer) {
440 Contact::const_iterator it = contact.trustScopeBegin();
441 Contact::const_iterator end = contact.trustScopeEnd();
442
443 while (it != end) {
444 sqlite3_prepare_v2(m_db,
445 "INSERT INTO TrustScope (contact_namespace, trust_scope) values (?, ?)",
446 -1, &stmt, 0);
447 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
448 sqlite3_bind_string(stmt, 2, it->first.toUri(), SQLITE_TRANSIENT);
Yingdi Yu1cc45d92015-02-09 14:19:54 -0800449 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700450 sqlite3_finalize(stmt);
451 it++;
Yingdi Yub2e747d2013-11-05 23:06:43 -0800452 }
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700453 }
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700454}
455
Yingdi Yufa4ce792014-02-06 18:09:22 -0800456
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800457shared_ptr<Contact>
458ContactStorage::getContact(const Name& identity) const
Yingdi Yufa4ce792014-02-06 18:09:22 -0800459{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800460 shared_ptr<Contact> contact;
461 Profile profile;
462
Yingdi Yufa4ce792014-02-06 18:09:22 -0800463 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700464 sqlite3_prepare_v2(m_db,
465 "SELECT contact_alias, contact_keyName, contact_key, notBefore, notAfter, \
466 is_introducer FROM Contact where contact_namespace=?",
467 -1, &stmt, 0);
468 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800469
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700470 if (sqlite3_step(stmt) == SQLITE_ROW) {
471 string alias = sqlite3_column_string(stmt, 0);
472 string keyName = sqlite3_column_string(stmt, 1);
Varun Patil3d850902020-11-23 12:19:14 +0530473 ndn::Buffer key(sqlite3_column_text(stmt, 2), sqlite3_column_bytes (stmt, 2));
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700474 time::system_clock::TimePoint notBefore =
475 time::fromUnixTimestamp(time::milliseconds(sqlite3_column_int64 (stmt, 3)));
476 time::system_clock::TimePoint notAfter =
477 time::fromUnixTimestamp(time::milliseconds(sqlite3_column_int64 (stmt, 4)));
478 int isIntroducer = sqlite3_column_int (stmt, 5);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800479
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700480 contact = make_shared<Contact>(identity, alias, Name(keyName),
481 notBefore, notAfter, key, isIntroducer);
482 }
483 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800484
Varun Patil3d850902020-11-23 12:19:14 +0530485 if (!static_cast<bool>(contact))
486 return contact;
487
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700488 sqlite3_prepare_v2(m_db,
489 "SELECT profile_type, profile_value FROM ContactProfile \
490 where profile_identity=?",
491 -1, &stmt, 0);
492 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700493
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700494 while (sqlite3_step(stmt) == SQLITE_ROW) {
495 string type = sqlite3_column_string(stmt, 0);
496 string value = sqlite3_column_string(stmt, 1);
497 profile[type] = value;
498 }
499 sqlite3_finalize(stmt);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800500 contact->setProfile(profile);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800501
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700502 if (contact->isIntroducer()) {
503 sqlite3_prepare_v2(m_db,
504 "SELECT trust_scope FROM TrustScope WHERE contact_namespace=?",
505 -1, &stmt, 0);
506 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800507
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700508 while (sqlite3_step(stmt) == SQLITE_ROW) {
509 Name scope(sqlite3_column_string(stmt, 0));
510 contact->addTrustScope(scope);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800511 }
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700512 sqlite3_finalize(stmt);
513 }
Yingdi Yufa4ce792014-02-06 18:09:22 -0800514
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800515 return contact;
Yingdi Yufa4ce792014-02-06 18:09:22 -0800516}
517
518
Yingdi Yub2e747d2013-11-05 23:06:43 -0800519void
Yingdi Yufa4ce792014-02-06 18:09:22 -0800520ContactStorage::updateIsIntroducer(const Name& identity, bool isIntroducer)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800521{
522 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700523 sqlite3_prepare_v2(m_db, "UPDATE Contact SET is_introducer=? WHERE contact_namespace=?",
524 -1, &stmt, 0);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800525 sqlite3_bind_int(stmt, 1, (isIntroducer ? 1 : 0));
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700526 sqlite3_bind_string(stmt, 2, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700527 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700528 sqlite3_finalize(stmt);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800529 return;
530}
531
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700532void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700533ContactStorage::updateAlias(const Name& identity, const string& alias)
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700534{
Yingdi Yu71c01872013-11-03 16:22:05 -0800535 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700536 sqlite3_prepare_v2(m_db, "UPDATE Contact SET contact_alias=? WHERE contact_namespace=?",
537 -1, &stmt, 0);
538 sqlite3_bind_string(stmt, 1, alias, SQLITE_TRANSIENT);
539 sqlite3_bind_string(stmt, 2, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700540 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700541 sqlite3_finalize(stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800542 return;
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700543}
544
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700545bool
Yingdi Yu71c01872013-11-03 16:22:05 -0800546ContactStorage::doesContactExist(const Name& name)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700547{
548 bool result = false;
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700549
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700550 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700551 sqlite3_prepare_v2(m_db, "SELECT count(*) FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
552 sqlite3_bind_string(stmt, 1, name.toUri(), SQLITE_TRANSIENT);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700553
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700554 int res = sqlite3_step(stmt);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700555
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700556 if (res == SQLITE_ROW) {
557 int countAll = sqlite3_column_int (stmt, 0);
558 if (countAll > 0)
559 result = true;
560 }
561
562 sqlite3_finalize(stmt);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700563 return result;
564}
565
Yingdi Yu76dd8002013-12-24 11:16:32 +0800566void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700567ContactStorage::getAllContacts(vector<shared_ptr<Contact> >& contacts) const
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700568{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700569 vector<Name> contactNames;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800570
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700571 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700572 sqlite3_prepare_v2(m_db, "SELECT contact_namespace FROM Contact", -1, &stmt, 0);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700573
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700574 while (sqlite3_step(stmt) == SQLITE_ROW) {
575 string identity = sqlite3_column_string(stmt, 0);
576 contactNames.push_back(Name(identity));
577 }
578 sqlite3_finalize(stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800579
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700580 for (vector<Name>::iterator it = contactNames.begin(); it != contactNames.end(); it++) {
581 shared_ptr<Contact> contact = getContact(*it);
582 if (static_cast<bool>(contact))
583 contacts.push_back(contact);
584 }
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700585}
Yingdi Yu3b318c12013-10-15 17:54:00 -0700586
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800587void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700588ContactStorage::updateDnsData(const Block& data, const string& name,
589 const string& type, const string& dataName)
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700590{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800591 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700592 sqlite3_prepare_v2(m_db,
593 "INSERT OR REPLACE INTO DnsData (dns_name, dns_type, dns_value, data_name) \
594 VALUES (?, ?, ?, ?)",
595 -1, &stmt, 0);
596 sqlite3_bind_string(stmt, 1, name, SQLITE_TRANSIENT);
597 sqlite3_bind_string(stmt, 2, type, SQLITE_TRANSIENT);
598 sqlite3_bind_block(stmt, 3, data, SQLITE_TRANSIENT);
599 sqlite3_bind_string(stmt, 4, dataName, SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700600 sqlite3_step(stmt);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800601
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800602 sqlite3_finalize(stmt);
603}
604
605shared_ptr<Data>
606ContactStorage::getDnsData(const Name& dataName)
607{
608 shared_ptr<Data> data;
609
610 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700611 sqlite3_prepare_v2(m_db, "SELECT dns_value FROM DnsData where data_name=?", -1, &stmt, 0);
612 sqlite3_bind_string(stmt, 1, dataName.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700613
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700614 if (sqlite3_step(stmt) == SQLITE_ROW) {
615 data = make_shared<Data>();
616 data->wireDecode(sqlite3_column_block(stmt, 0));
617 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800618 sqlite3_finalize(stmt);
619
620 return data;
621}
622
623shared_ptr<Data>
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700624ContactStorage::getDnsData(const string& name, const string& type)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800625{
626 shared_ptr<Data> data;
627
628 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700629 sqlite3_prepare_v2(m_db, "SELECT dns_value FROM DnsData where dns_name=? and dns_type=?",
630 -1, &stmt, 0);
631 sqlite3_bind_string(stmt, 1, name, SQLITE_TRANSIENT);
632 sqlite3_bind_string(stmt, 2, type, SQLITE_TRANSIENT);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700633
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700634 if (sqlite3_step(stmt) == SQLITE_ROW) {
635 data = make_shared<Data>();
636 data->wireDecode(sqlite3_column_block(stmt, 0));
637 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800638 sqlite3_finalize(stmt);
639
640 return data;
641}
642
Yingdi Yueb692ac2015-02-10 18:46:18 -0800643} // namespace chronochat