blob: d5aeee86582d2b61d6ee854b84c89fdfbb317735 [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
11#include "contact-storage.h"
Yingdi Yud04ed1a2013-10-14 14:07:03 -070012
Yingdi Yud04ed1a2013-10-14 14:07:03 -070013#include <boost/filesystem.hpp>
Yingdi Yu348f5ea2014-03-01 14:47:25 -080014#include <cryptopp/sha.h>
15#include <cryptopp/filters.h>
16#include <cryptopp/hex.h>
17#include <cryptopp/files.h>
Yingdi Yu3b318c12013-10-15 17:54:00 -070018#include "logging.h"
Yingdi Yud04ed1a2013-10-14 14:07:03 -070019
Yingdi Yud04ed1a2013-10-14 14:07:03 -070020using namespace ndn;
21namespace fs = boost::filesystem;
22
Yingdi Yu348f5ea2014-03-01 14:47:25 -080023INIT_LOGGER ("chronos.ContactStorage");
Yingdi Yu3b318c12013-10-15 17:54:00 -070024
Yingdi Yufa4ce792014-02-06 18:09:22 -080025namespace chronos{
26
Yingdi Yu17032f82014-03-25 15:48:23 -070027using ndn::shared_ptr;
28
29const std::string INIT_SP_TABLE = "\
Yingdi Yu3b318c12013-10-15 17:54:00 -070030CREATE TABLE IF NOT EXISTS \n \
31 SelfProfile( \n \
Yingdi Yu3b318c12013-10-15 17:54:00 -070032 profile_type BLOB NOT NULL, \n \
Yingdi Yu54dcecc2013-10-17 15:07:17 -070033 profile_value BLOB NOT NULL, \n \
34 \
Yingdi Yu348f5ea2014-03-01 14:47:25 -080035 PRIMARY KEY (profile_type) \n \
Yingdi Yu3b318c12013-10-15 17:54:00 -070036 ); \n \
37 \
Yingdi Yu348f5ea2014-03-01 14:47:25 -080038CREATE INDEX sp_index ON SelfProfile(profile_type); \n \
39"; // user's own profile;
Yingdi Yu3b318c12013-10-15 17:54:00 -070040
Yingdi Yu17032f82014-03-25 15:48:23 -070041const std::string INIT_SE_TABLE = "\
Yingdi Yu3b318c12013-10-15 17:54:00 -070042CREATE TABLE IF NOT EXISTS \n \
Yingdi Yuec3d9a32013-10-18 18:35:09 -070043 SelfEndorse( \n \
Yingdi Yu3b318c12013-10-15 17:54:00 -070044 identity BLOB NOT NULL UNIQUE, \n \
Yingdi Yuec3d9a32013-10-18 18:35:09 -070045 endorse_data BLOB NOT NULL, \n \
Yingdi Yu3b318c12013-10-15 17:54:00 -070046 \
47 PRIMARY KEY (identity) \n \
48 ); \n \
Yingdi Yuec3d9a32013-10-18 18:35:09 -070049CREATE INDEX se_index ON SelfEndorse(identity); \n \
Yingdi Yu348f5ea2014-03-01 14:47:25 -080050"; // user's self endorse cert;
Yingdi Yud04ed1a2013-10-14 14:07:03 -070051
Yingdi Yu17032f82014-03-25 15:48:23 -070052const std::string INIT_CONTACT_TABLE = "\
Yingdi Yud04ed1a2013-10-14 14:07:03 -070053CREATE TABLE IF NOT EXISTS \n \
Yingdi Yu71c01872013-11-03 16:22:05 -080054 Contact( \n \
Yingdi Yud04ed1a2013-10-14 14:07:03 -070055 contact_namespace BLOB NOT NULL, \n \
56 contact_alias BLOB NOT NULL, \n \
Yingdi Yu348f5ea2014-03-01 14:47:25 -080057 contact_keyName BLOB NOT NULL, \n \
58 contact_key BLOB NOT NULL, \n \
59 notBefore INTEGER DEFAULT 0, \n \
60 notAfter INTEGER DEFAULT 0, \n \
Yingdi Yu71c01872013-11-03 16:22:05 -080061 is_introducer INTEGER DEFAULT 0, \n \
Yingdi Yud04ed1a2013-10-14 14:07:03 -070062 \
63 PRIMARY KEY (contact_namespace) \n \
64 ); \n \
65 \
Yingdi Yub2e747d2013-11-05 23:06:43 -080066CREATE INDEX contact_index ON Contact(contact_namespace); \n \
Yingdi Yu348f5ea2014-03-01 14:47:25 -080067"; // contact's basic info
Yingdi Yud04ed1a2013-10-14 14:07:03 -070068
Yingdi Yu17032f82014-03-25 15:48:23 -070069const std::string INIT_TS_TABLE = "\
Yingdi Yud04ed1a2013-10-14 14:07:03 -070070CREATE TABLE IF NOT EXISTS \n \
Yingdi Yu71c01872013-11-03 16:22:05 -080071 TrustScope( \n \
Yingdi Yub2e747d2013-11-05 23:06:43 -080072 id INTEGER PRIMARY KEY AUTOINCREMENT, \n \
Yingdi Yud04ed1a2013-10-14 14:07:03 -070073 contact_namespace BLOB NOT NULL, \n \
Yingdi Yub2e747d2013-11-05 23:06:43 -080074 trust_scope BLOB NOT NULL \n \
Yingdi Yud04ed1a2013-10-14 14:07:03 -070075 ); \n \
76 \
Yingdi Yub2e747d2013-11-05 23:06:43 -080077CREATE INDEX ts_index ON TrustScope(contact_namespace); \n \
Yingdi Yu348f5ea2014-03-01 14:47:25 -080078"; // contact's trust scope;
Yingdi Yub2e747d2013-11-05 23:06:43 -080079
Yingdi Yu17032f82014-03-25 15:48:23 -070080const std::string INIT_CP_TABLE = "\
Yingdi Yub2e747d2013-11-05 23:06:43 -080081CREATE TABLE IF NOT EXISTS \n \
82 ContactProfile( \n \
83 profile_identity BLOB NOT NULL, \n \
84 profile_type BLOB NOT NULL, \n \
85 profile_value BLOB NOT NULL, \n \
86 endorse INTEGER NOT NULL, \n \
87 \
88 PRIMARY KEY (profile_identity, profile_type) \n \
89 ); \n \
90 \
91CREATE INDEX cp_index ON ContactProfile(profile_identity); \n \
Yingdi Yu348f5ea2014-03-01 14:47:25 -080092"; // contact's profile
Yingdi Yub2e747d2013-11-05 23:06:43 -080093
Yingdi Yu17032f82014-03-25 15:48:23 -070094const std::string INIT_PE_TABLE = "\
Yingdi Yub2e747d2013-11-05 23:06:43 -080095CREATE TABLE IF NOT EXISTS \n \
96 ProfileEndorse( \n \
97 identity BLOB NOT NULL UNIQUE, \n \
98 endorse_data BLOB NOT NULL, \n \
99 \
100 PRIMARY KEY (identity) \n \
101 ); \n \
102 \
103CREATE INDEX pe_index ON ProfileEndorse(identity); \n \
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800104"; // user's endorsement on contacts
Yingdi Yub2e747d2013-11-05 23:06:43 -0800105
Yingdi Yu17032f82014-03-25 15:48:23 -0700106const std::string INIT_CE_TABLE = "\
Yingdi Yub2e747d2013-11-05 23:06:43 -0800107CREATE TABLE IF NOT EXISTS \n \
108 CollectEndorse( \n \
Yingdi Yub2e747d2013-11-05 23:06:43 -0800109 endorser BLOB NOT NULL, \n \
110 endorse_name BLOB NOT NULL, \n \
111 endorse_data BLOB NOT NULL, \n \
112 \
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800113 PRIMARY KEY (endorser) \n \
Yingdi Yub2e747d2013-11-05 23:06:43 -0800114 ); \n \
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800115"; // contact's endorsements on the user
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700116
Yingdi Yu17032f82014-03-25 15:48:23 -0700117const std::string INIT_DD_TABLE = "\
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800118CREATE TABLE IF NOT EXISTS \n \
119 DnsData( \n \
120 dns_name BLOB NOT NULL, \n \
121 dns_type BLOB NOT NULL, \n \
122 data_name BLOB NOT NULL, \n \
123 dns_value BLOB NOT NULL, \n \
124 \
125 PRIMARY KEY (dns_name, dns_type) \n \
126 ); \
127CREATE INDEX dd_index ON DnsData(dns_name, dns_type); \n \
128CREATE INDEX dd_index2 ON DnsData(data_name); \n \
129"; // dns data;
130
131ContactStorage::ContactStorage(const Name& identity)
132 : m_identity(identity)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700133{
134 fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
135 fs::create_directories (chronosDir);
136
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800137 int res = sqlite3_open((chronosDir / getDBName()).c_str (), &m_db);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700138 if (res != SQLITE_OK)
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800139 throw Error("Chronos DB cannot be open/created");
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700140
Yingdi Yufa4ce792014-02-06 18:09:22 -0800141 initializeTable("SelfProfile", INIT_SP_TABLE);
142 initializeTable("SelfEndorse", INIT_SE_TABLE);
143 initializeTable("Contact", INIT_CONTACT_TABLE);
144 initializeTable("TrustScope", INIT_TS_TABLE);
145 initializeTable("ContactProfile", INIT_CP_TABLE);
146 initializeTable("ProfileEndorse", INIT_PE_TABLE);
147 initializeTable("CollectEndorse", INIT_CE_TABLE);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800148 initializeTable("DnsData", INIT_DD_TABLE);
Yingdi Yu3b318c12013-10-15 17:54:00 -0700149
Yingdi Yu3b318c12013-10-15 17:54:00 -0700150}
151
Yingdi Yu17032f82014-03-25 15:48:23 -0700152std::string
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800153ContactStorage::getDBName()
154{
Yingdi Yu17032f82014-03-25 15:48:23 -0700155 std::string dbName("chronos-");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800156
Yingdi Yu17032f82014-03-25 15:48:23 -0700157 std::stringstream ss;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800158 {
159 using namespace CryptoPP;
160
161 SHA256 hash;
162 StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
163 new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
164 }
165 dbName.append(ss.str()).append(".db");
166
167 return dbName;
168}
169
Yingdi Yu3b318c12013-10-15 17:54:00 -0700170void
Yingdi Yu17032f82014-03-25 15:48:23 -0700171ContactStorage::initializeTable(const std::string& tableName, const std::string& sqlCreateStmt)
Yingdi Yu3b318c12013-10-15 17:54:00 -0700172{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800173 sqlite3_stmt *stmt;
174 sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name=?", -1, &stmt, 0);
175 sqlite3_bind_text(stmt, 1, tableName.c_str(), tableName.size(), SQLITE_TRANSIENT);
176 int res = sqlite3_step (stmt);
177
178 bool tableExist = false;
179 if (res == SQLITE_ROW)
180 tableExist = true;
Yingdi Yu3b318c12013-10-15 17:54:00 -0700181 sqlite3_finalize (stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800182
183 if(!tableExist)
184 {
185 char *errmsg = 0;
186 res = sqlite3_exec (m_db, sqlCreateStmt.c_str (), NULL, NULL, &errmsg);
187 if (res != SQLITE_OK && errmsg != 0)
188 throw Error("Init \"error\" in " + tableName);
189 }
Yingdi Yu3b318c12013-10-15 17:54:00 -0700190}
191
Yingdi Yu76dd8002013-12-24 11:16:32 +0800192shared_ptr<Profile>
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800193ContactStorage::getSelfProfile()
Yingdi Yufa4ce792014-02-06 18:09:22 -0800194{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800195 shared_ptr<Profile> profile = make_shared<Profile>(m_identity);
Yingdi Yu3b318c12013-10-15 17:54:00 -0700196 sqlite3_stmt *stmt;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800197 sqlite3_prepare_v2 (m_db, "SELECT profile_type, profile_value FROM SelfProfile", -1, &stmt, 0);
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700198
Yingdi Yufa4ce792014-02-06 18:09:22 -0800199 while( sqlite3_step (stmt) == SQLITE_ROW)
Yingdi Yu3b318c12013-10-15 17:54:00 -0700200 {
Yingdi Yu17032f82014-03-25 15:48:23 -0700201 std::string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
202 std::string profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
Yingdi Yufa4ce792014-02-06 18:09:22 -0800203 (*profile)[profileType] = profileValue;
Yingdi Yu3b318c12013-10-15 17:54:00 -0700204 }
205
Yingdi Yu72781e52013-11-06 23:00:21 -0800206 sqlite3_finalize(stmt);
207
Yingdi Yu3b318c12013-10-15 17:54:00 -0700208 return profile;
209}
Yingdi Yuae8217c2013-11-09 00:03:26 -0800210
Yingdi Yufa4ce792014-02-06 18:09:22 -0800211void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800212ContactStorage::addSelfEndorseCertificate(const EndorseCertificate& newEndorseCertificate)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800213{
214 const Block& newEndorseCertificateBlock = newEndorseCertificate.wireEncode();
215
216 sqlite3_stmt *stmt;
217 sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO SelfEndorse (identity, endorse_data) values (?, ?)", -1, &stmt, 0);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800218 sqlite3_bind_text(stmt, 1, m_identity.toUri().c_str(), m_identity.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800219 sqlite3_bind_text(stmt, 2, reinterpret_cast<const char*>(newEndorseCertificateBlock.wire()), newEndorseCertificateBlock.size(), SQLITE_TRANSIENT);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800220 int res = sqlite3_step(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800221
222 sqlite3_finalize (stmt);
223}
224
Yingdi Yufa4ce792014-02-06 18:09:22 -0800225void
226ContactStorage::addEndorseCertificate(const EndorseCertificate& endorseCertificate, const Name& identity)
227{
228 const Block& newEndorseCertificateBlock = endorseCertificate.wireEncode();
229
230 sqlite3_stmt *stmt;
231 sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO ProfileEndorse (identity, endorse_data) values (?, ?)", -1, &stmt, 0);
232 sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800233 sqlite3_bind_text(stmt, 2, reinterpret_cast<const char*>(newEndorseCertificateBlock.wire()), newEndorseCertificateBlock.size(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800234 sqlite3_step(stmt);
235
236 sqlite3_finalize (stmt);
237}
238
239void
240ContactStorage::updateCollectEndorse(const EndorseCertificate& endorseCertificate)
241{
242 Name endorserName = endorseCertificate.getSigner();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800243 Name certName = endorseCertificate.getName();
Yingdi Yufa4ce792014-02-06 18:09:22 -0800244
245 sqlite3_stmt *stmt;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800246 sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO CollectEndorse (endorser, endorse_name, endorse_data) VALUES (?, ?, ?, ?)", -1, &stmt, 0);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800247 sqlite3_bind_text(stmt, 1, endorserName.toUri().c_str(), endorserName.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800248 sqlite3_bind_text(stmt, 2, certName.toUri().c_str(), certName.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800249 const Block &block = endorseCertificate.wireEncode();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800250 sqlite3_bind_text(stmt, 3, reinterpret_cast<const char*>(block.wire()), block.size(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800251 int res = sqlite3_step (stmt);
252 sqlite3_finalize (stmt);
253 return;
254}
255
256void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800257ContactStorage::getCollectEndorse(EndorseCollection& endorseCollection)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800258{
259 sqlite3_stmt *stmt;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800260 sqlite3_prepare_v2 (m_db, "SELECT endorse_name, endorse_data FROM CollectEndorse", -1, &stmt, 0);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800261
262 while(sqlite3_step (stmt) == SQLITE_ROW)
263 {
Yingdi Yu17032f82014-03-25 15:48:23 -0700264 std::string certName(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes(stmt, 1));
265 std::stringstream ss;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800266 {
267 using namespace CryptoPP;
268 SHA256 hash;
269
270 StringSource(sqlite3_column_text(stmt, 1), sqlite3_column_bytes (stmt, 0), true,
271 new HashFilter(hash, new FileSink(ss)));
272 }
273 EndorseCollection::Endorsement* endorsement = endorseCollection.add_endorsement();
274 endorsement->set_certname(certName);
275 endorsement->set_hash(ss.str());
Yingdi Yufa4ce792014-02-06 18:09:22 -0800276 }
277
278 sqlite3_finalize (stmt);
279}
280
281void
Yingdi Yu17032f82014-03-25 15:48:23 -0700282ContactStorage::getEndorseList(const Name& identity, std::vector<std::string>& endorseList)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800283{
284 sqlite3_stmt *stmt;
285 sqlite3_prepare_v2 (m_db, "SELECT profile_type FROM ContactProfile WHERE profile_identity=? AND endorse=1 ORDER BY profile_type", -1, &stmt, 0);
286 sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
287
288 while( sqlite3_step (stmt) == SQLITE_ROW)
289 {
Yingdi Yu17032f82014-03-25 15:48:23 -0700290 std::string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
Yingdi Yufa4ce792014-02-06 18:09:22 -0800291 endorseList.push_back(profileType);
292 }
293 sqlite3_finalize (stmt);
294}
295
296
Yingdi Yuae8217c2013-11-09 00:03:26 -0800297void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800298ContactStorage::removeContact(const Name& identityName)
Yingdi Yuae8217c2013-11-09 00:03:26 -0800299{
Yingdi Yu17032f82014-03-25 15:48:23 -0700300 std::string identity = identityName.toUri();
Yingdi Yuae8217c2013-11-09 00:03:26 -0800301
Yingdi Yuae8217c2013-11-09 00:03:26 -0800302 sqlite3_stmt *stmt;
303 sqlite3_prepare_v2 (m_db, "DELETE FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
304 sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size (), SQLITE_TRANSIENT);
305 int res = sqlite3_step (stmt);
306 sqlite3_finalize (stmt);
307
308 sqlite3_prepare_v2 (m_db, "DELETE FROM ContactProfile WHERE profile_identity=?", -1, &stmt, 0);
309 sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size (), SQLITE_TRANSIENT);
310 res = sqlite3_step (stmt);
311 sqlite3_finalize (stmt);
312
Yingdi Yufa4ce792014-02-06 18:09:22 -0800313 sqlite3_prepare_v2 (m_db, "DELETE FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
314 sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size (), SQLITE_TRANSIENT);
315 res = sqlite3_step (stmt);
316 sqlite3_finalize (stmt);
Yingdi Yuae8217c2013-11-09 00:03:26 -0800317}
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700318
319void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800320ContactStorage::addContact(const Contact& contact)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700321{
Yingdi Yu71c01872013-11-03 16:22:05 -0800322 if(doesContactExist(contact.getNameSpace()))
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800323 throw Error("Normal Contact has already existed");
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700324
Yingdi Yu17032f82014-03-25 15:48:23 -0700325 std::string identity = contact.getNameSpace().toUri();
Yingdi Yu71c01872013-11-03 16:22:05 -0800326 bool isIntroducer = contact.isIntroducer();
327
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700328 sqlite3_stmt *stmt;
329 sqlite3_prepare_v2 (m_db,
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800330 "INSERT INTO Contact (contact_namespace, contact_alias, contact_keyName, contact_key, notBefore, notAfter, is_introducer) values (?, ?, ?, ?, ?, ?, ?)",
331 -1,
332 &stmt,
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700333 0);
334
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800335 sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size (), SQLITE_TRANSIENT);
Yingdi Yu71c01872013-11-03 16:22:05 -0800336 sqlite3_bind_text(stmt, 2, contact.getAlias().c_str(), contact.getAlias().size(), SQLITE_TRANSIENT);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800337 sqlite3_bind_text(stmt, 3, contact.getPublicKeyName().toUri().c_str(), contact.getPublicKeyName().toUri().size(), SQLITE_TRANSIENT);
338 sqlite3_bind_text(stmt, 4, reinterpret_cast<const char*>(contact.getPublicKey().get().buf()), contact.getPublicKey().get().size(), SQLITE_TRANSIENT);
Yingdi Yua7876722014-03-25 14:46:55 -0700339 sqlite3_bind_int64(stmt, 5, time::toUnixTimestamp(contact.getNotBefore()).count());
340 sqlite3_bind_int64(stmt, 6, time::toUnixTimestamp(contact.getNotAfter()).count());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800341 sqlite3_bind_int(stmt, 7, (isIntroducer ? 1 : 0));
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700342
343 int res = sqlite3_step (stmt);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800344
345 // _LOG_DEBUG("addContact: " << res);
346
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700347 sqlite3_finalize (stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800348
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800349 const Profile& profile = contact.getProfile();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800350 Profile::const_iterator it = profile.begin();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800351
Yingdi Yub2e747d2013-11-05 23:06:43 -0800352 for(; it != profile.end(); it++)
353 {
354 sqlite3_prepare_v2 (m_db,
355 "INSERT INTO ContactProfile (profile_identity, profile_type, profile_value, endorse) values (?, ?, ?, 0)",
356 -1,
357 &stmt,
358 0);
359 sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size (), SQLITE_TRANSIENT);
360 sqlite3_bind_text(stmt, 2, it->first.c_str(), it->first.size(), SQLITE_TRANSIENT);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800361 sqlite3_bind_text(stmt, 3, it->second.c_str(), it->second.size(), SQLITE_TRANSIENT);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800362 res = sqlite3_step (stmt);
363 sqlite3_finalize (stmt);
364 }
365
Yingdi Yu71c01872013-11-03 16:22:05 -0800366 if(isIntroducer)
367 {
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800368 Contact::const_iterator it = contact.trustScopeBegin();
369 Contact::const_iterator end = contact.trustScopeEnd();
370
371 while(it != end)
Yingdi Yu71c01872013-11-03 16:22:05 -0800372 {
373 sqlite3_prepare_v2 (m_db,
374 "INSERT INTO TrustScope (contact_namespace, trust_scope) values (?, ?)",
375 -1,
376 &stmt,
377 0);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800378 sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size (), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800379 sqlite3_bind_text(stmt, 2, it->first.toUri().c_str(), it->first.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yu71c01872013-11-03 16:22:05 -0800380 res = sqlite3_step (stmt);
381 sqlite3_finalize (stmt);
382 it++;
383 }
384 }
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700385}
386
Yingdi Yufa4ce792014-02-06 18:09:22 -0800387
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800388shared_ptr<Contact>
389ContactStorage::getContact(const Name& identity) const
Yingdi Yufa4ce792014-02-06 18:09:22 -0800390{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800391 shared_ptr<Contact> contact;
392 Profile profile;
393
Yingdi Yufa4ce792014-02-06 18:09:22 -0800394 sqlite3_stmt *stmt;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800395 sqlite3_prepare_v2 (m_db, "SELECT contact_alias, contact_keyName, contact_key, notBefore, notAfter, is_introducer FROM Contact where contact_namespace=?", -1, &stmt, 0);
396 sqlite3_bind_text (stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
397
398 if(sqlite3_step (stmt) == SQLITE_ROW)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800399 {
Yingdi Yu17032f82014-03-25 15:48:23 -0700400 std::string alias(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
401 std::string keyName(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800402 PublicKey key(sqlite3_column_text(stmt, 2), sqlite3_column_bytes (stmt, 2));
Yingdi Yua7876722014-03-25 14:46:55 -0700403 time::system_clock::TimePoint notBefore = time::fromUnixTimestamp(time::milliseconds(sqlite3_column_int64 (stmt, 3)));
404 time::system_clock::TimePoint notAfter = time::fromUnixTimestamp(time::milliseconds(sqlite3_column_int64 (stmt, 4)));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800405 int isIntroducer = sqlite3_column_int (stmt, 5);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800406
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800407 contact = shared_ptr<Contact>(new Contact(identity, alias, Name(keyName), notBefore, notAfter, key, isIntroducer));
408 }
409 sqlite3_finalize (stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800410
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800411 sqlite3_prepare_v2 (m_db, "SELECT profile_type, profile_value FROM ContactProfile where profile_identity=?", -1, &stmt, 0);
412 sqlite3_bind_text (stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
413
414 while(sqlite3_step (stmt) == SQLITE_ROW)
415 {
Yingdi Yu17032f82014-03-25 15:48:23 -0700416 std::string type(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
417 std::string value(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800418 profile[type] = value;
419 }
420 sqlite3_finalize (stmt);
421 contact->setProfile(profile);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800422
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800423 if(contact->isIntroducer())
424 {
425 sqlite3_prepare_v2 (m_db, "SELECT trust_scope FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
426 sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800427
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800428 while(sqlite3_step (stmt) == SQLITE_ROW)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800429 {
Yingdi Yu17032f82014-03-25 15:48:23 -0700430 Name scope(std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800431 contact->addTrustScope(scope);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800432 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800433 sqlite3_finalize (stmt);
434 }
Yingdi Yufa4ce792014-02-06 18:09:22 -0800435
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800436 return contact;
Yingdi Yufa4ce792014-02-06 18:09:22 -0800437}
438
439
Yingdi Yub2e747d2013-11-05 23:06:43 -0800440void
Yingdi Yufa4ce792014-02-06 18:09:22 -0800441ContactStorage::updateIsIntroducer(const Name& identity, bool isIntroducer)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800442{
443 sqlite3_stmt *stmt;
444 sqlite3_prepare_v2 (m_db, "UPDATE Contact SET is_introducer=? WHERE contact_namespace=?", -1, &stmt, 0);
445 sqlite3_bind_int(stmt, 1, (isIntroducer ? 1 : 0));
446 sqlite3_bind_text(stmt, 2, identity.toUri().c_str(), identity.toUri().size (), SQLITE_TRANSIENT);
447 int res = sqlite3_step (stmt);
448 sqlite3_finalize (stmt);
449 return;
450}
451
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700452void
Yingdi Yu17032f82014-03-25 15:48:23 -0700453ContactStorage::updateAlias(const Name& identity, std::string alias)
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700454{
Yingdi Yu71c01872013-11-03 16:22:05 -0800455 sqlite3_stmt *stmt;
456 sqlite3_prepare_v2 (m_db, "UPDATE Contact SET contact_alias=? WHERE contact_namespace=?", -1, &stmt, 0);
457 sqlite3_bind_text(stmt, 1, alias.c_str(), alias.size(), SQLITE_TRANSIENT);
458 sqlite3_bind_text(stmt, 2, identity.toUri().c_str(), identity.toUri().size (), SQLITE_TRANSIENT);
459 int res = sqlite3_step (stmt);
460 sqlite3_finalize (stmt);
461 return;
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700462}
463
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700464bool
Yingdi Yu71c01872013-11-03 16:22:05 -0800465ContactStorage::doesContactExist(const Name& name)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700466{
467 bool result = false;
468
469 sqlite3_stmt *stmt;
Yingdi Yu71c01872013-11-03 16:22:05 -0800470 sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700471 sqlite3_bind_text(stmt, 1, name.toUri().c_str(), name.toUri().size(), SQLITE_TRANSIENT);
472
473 int res = sqlite3_step (stmt);
474
475 if (res == SQLITE_ROW)
476 {
477 int countAll = sqlite3_column_int (stmt, 0);
478 if (countAll > 0)
479 result = true;
480 }
481 sqlite3_finalize (stmt);
482 return result;
483}
484
Yingdi Yu76dd8002013-12-24 11:16:32 +0800485void
Yingdi Yu17032f82014-03-25 15:48:23 -0700486ContactStorage::getAllContacts(std::vector<shared_ptr<Contact> >& contacts) const
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700487{
Yingdi Yu17032f82014-03-25 15:48:23 -0700488 std::vector<Name> contactNames;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800489
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700490 sqlite3_stmt *stmt;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800491 sqlite3_prepare_v2 (m_db, "SELECT contact_namespace FROM Contact", -1, &stmt, 0);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700492
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800493 while(sqlite3_step (stmt) == SQLITE_ROW)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700494 {
Yingdi Yu17032f82014-03-25 15:48:23 -0700495 std::string identity(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes(stmt, 0));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800496 contactNames.push_back(Name(identity));
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700497 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800498 sqlite3_finalize (stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800499
Yingdi Yu17032f82014-03-25 15:48:23 -0700500 std::vector<Name>::iterator it = contactNames.begin();
501 std::vector<Name>::iterator end = contactNames.end();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800502 for(; it != end; it++)
Yingdi Yu71c01872013-11-03 16:22:05 -0800503 {
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800504 shared_ptr<Contact> contact = getContact(*it);
505 if(static_cast<bool>(contact))
506 contacts.push_back(contact);
Yingdi Yu71c01872013-11-03 16:22:05 -0800507 }
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700508}
Yingdi Yu3b318c12013-10-15 17:54:00 -0700509
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800510void
511ContactStorage::updateDnsData(const Block& data,
Yingdi Yu17032f82014-03-25 15:48:23 -0700512 const std::string& name,
513 const std::string& type,
514 const std::string& dataName)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800515{
516 sqlite3_stmt *stmt;
517 sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO DnsData (dns_name, dns_type, dns_value, data_name) VALUES (?, ?, ?, ?)", -1, &stmt, 0);
518 sqlite3_bind_text(stmt, 1, name.c_str(), name.size(), SQLITE_TRANSIENT);
519 sqlite3_bind_text(stmt, 2, type.c_str(), type.size(), SQLITE_TRANSIENT);
520 sqlite3_bind_text(stmt, 3, reinterpret_cast<const char*>(data.wire()), data.size(), SQLITE_TRANSIENT);
521 sqlite3_bind_text(stmt, 4, dataName.c_str(), dataName.size(), SQLITE_TRANSIENT);
522 int res = sqlite3_step(stmt);
523
524 // _LOG_DEBUG("updateDnsData " << res);
525 sqlite3_finalize(stmt);
526}
527
528shared_ptr<Data>
529ContactStorage::getDnsData(const Name& dataName)
530{
531 shared_ptr<Data> data;
532
533 sqlite3_stmt *stmt;
534 sqlite3_prepare_v2 (m_db, "SELECT dns_value FROM DnsData where data_name=?", -1, &stmt, 0);
535 sqlite3_bind_text(stmt, 1, dataName.toUri().c_str(), dataName.toUri().size(), SQLITE_TRANSIENT);
536
537 if(sqlite3_step (stmt) == SQLITE_ROW)
538 {
539 data = make_shared<Data>();
540 data->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
541 }
542 sqlite3_finalize(stmt);
543
544 return data;
545}
546
547shared_ptr<Data>
Yingdi Yu17032f82014-03-25 15:48:23 -0700548ContactStorage::getDnsData(const std::string& name, const std::string& type)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800549{
550 shared_ptr<Data> data;
551
552 sqlite3_stmt *stmt;
553 sqlite3_prepare_v2 (m_db, "SELECT dns_value FROM DnsData where dns_name=? and dns_type=?", -1, &stmt, 0);
554 sqlite3_bind_text(stmt, 1, name.c_str(), name.size(), SQLITE_TRANSIENT);
555 sqlite3_bind_text(stmt, 2, type.c_str(), type.size(), SQLITE_TRANSIENT);
556
557 if(sqlite3_step (stmt) == SQLITE_ROW)
558 {
559 data = make_shared<Data>();
560 data->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
561 }
562 sqlite3_finalize(stmt);
563
564 return data;
565}
566
Yingdi Yufa4ce792014-02-06 18:09:22 -0800567}//chronos