blob: 4ca036171b3e858ab1635f23ef87f4698562f42e [file] [log] [blame]
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev1cf5c432017-01-13 23:22:15 -08003 * Copyright (c) 2013-2017, Regents of the University of California.
Alexander Afanasyev68f2a952013-01-08 14:34:16 -08004 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08005 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
Alexander Afanasyev68f2a952013-01-08 14:34:16 -08006 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08007 * ChronoShare is free software: you can redistribute it and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080010 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -080011 * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080014 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -080015 * You should have received copies of the GNU General Public License along with
16 * ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * See AUTHORS.md for complete list of ChronoShare authors and contributors.
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080019 */
20
Alexander Afanasyevf4cde4e2016-12-25 13:42:57 -080021#include "object-manager.hpp"
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080022#include "object-db.hpp"
Lijing Wang9f77a8c2016-12-25 14:44:04 -080023#include "core/logging.hpp"
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080024
25#include <sys/stat.h>
26
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080027#include <boost/filesystem/fstream.hpp>
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080028#include <boost/lexical_cast.hpp>
Lijing Wang9f77a8c2016-12-25 14:44:04 -080029
30#include <ndn-cxx/util/string-helper.hpp>
31
32namespace ndn {
33namespace chronoshare {
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080034
Alexander Afanasyev1cf5c432017-01-13 23:22:15 -080035_LOG_INIT(Object.Manager);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -080036
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080037namespace fs = boost::filesystem;
Lijing Wang9f77a8c2016-12-25 14:44:04 -080038using util::Sha256;
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080039
40const int MAX_FILE_SEGMENT_SIZE = 1024;
41
Lijing Wang9f77a8c2016-12-25 14:44:04 -080042ObjectManager::ObjectManager(Face& face, KeyChain& keyChain,
43 const fs::path& folder, const std::string& appName)
44 : m_face(face)
45 , m_keyChain(keyChain)
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080046 , m_folder(folder / ".chronoshare")
47 , m_appName(appName)
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080048{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080049 fs::create_directories(m_folder);
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080050}
51
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080052ObjectManager::~ObjectManager()
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080053{
54}
55
Alexander Afanasyev4d086752013-02-07 13:06:04 -080056// /<devicename>/<appname>/file/<hash>/<segment>
Lijing Wang9f77a8c2016-12-25 14:44:04 -080057std::tuple<ConstBufferPtr /*object-db name*/, size_t /* number of segments*/>
58ObjectManager::localFileToObjects(const fs::path& file, const Name& deviceName)
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080059{
Lijing Wang9f77a8c2016-12-25 14:44:04 -080060 fs::ifstream input1(file, std::ios::in | std::ios::binary);
61 Sha256 fileHash(input1);
62 ObjectDb fileDb(m_folder, fileHash.toString());
Alexander Afanasyev49a30d02013-01-21 21:38:48 -080063
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080064 fs::ifstream iff(file, std::ios::in | std::ios::binary);
Alexander Afanasyevdbc06712013-01-08 18:30:28 -080065 sqlite3_int64 segment = 0;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080066 while (iff.good() && !iff.eof()) {
67 char buf[MAX_FILE_SEGMENT_SIZE];
68 iff.read(buf, MAX_FILE_SEGMENT_SIZE);
69 if (iff.gcount() == 0) {
70 // stupid streams...
71 break;
Alexander Afanasyev68f2a952013-01-08 14:34:16 -080072 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080073
Lijing Wang9f77a8c2016-12-25 14:44:04 -080074 Name name = Name("/");
75 name.append(deviceName)
76 .append(m_appName)
77 .append("file")
78 .appendImplicitSha256Digest(fileHash.computeDigest())
79 .appendNumber(segment);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080080
Lijing Wang9f77a8c2016-12-25 14:44:04 -080081 shared_ptr<Data> data = make_shared<Data>();
82 data->setName(name);
83 data->setFreshnessPeriod(time::seconds(60));
84 data->setContent(reinterpret_cast<const uint8_t*>(&buf), iff.gcount());
85 m_keyChain.sign(*data);
86 m_face.put(*data);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080087
Lijing Wang9f77a8c2016-12-25 14:44:04 -080088 fileDb.saveContentObject(deviceName, segment, *data);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080089
90 segment++;
91 }
Alexander Afanasyevac704622013-01-25 17:50:34 -080092 if (segment == 0) // handle empty files
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080093 {
Lijing Wang9f77a8c2016-12-25 14:44:04 -080094 Name name = Name("/");
95 name.append(m_appName)
96 .append("file")
97 .appendImplicitSha256Digest(fileHash.computeDigest())
98 .append(deviceName)
99 .appendNumber(0);
100
101 shared_ptr<Data> data = make_shared<Data>();
102 data->setName(name);
103 data->setFreshnessPeriod(time::seconds(0));
104 data->setContent(0, 0);
105 m_keyChain.sign(*data);
106 m_face.put(*data);
107
108 fileDb.saveContentObject(deviceName, 0, *data);
Alexander Afanasyevac704622013-01-25 17:50:34 -0800109
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800110 segment++;
111 }
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800112
Lijing Wang9f77a8c2016-12-25 14:44:04 -0800113 return std::make_tuple(fileHash.computeDigest(), segment);
Alexander Afanasyev68f2a952013-01-08 14:34:16 -0800114}
Alexander Afanasyevdbc06712013-01-08 18:30:28 -0800115
116bool
Lijing Wang9f77a8c2016-12-25 14:44:04 -0800117ObjectManager::objectsToLocalFile(/*in*/ const Name& deviceName, /*in*/ const Buffer& fileHash,
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800118 /*out*/ const fs::path& file)
Alexander Afanasyevdbc06712013-01-08 18:30:28 -0800119{
Lijing Wang9f77a8c2016-12-25 14:44:04 -0800120 std::string hashStr = toHex(fileHash);
121 if (!ObjectDb::doesExist(m_folder, deviceName, hashStr)) {
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800122 _LOG_ERROR("ObjectDb for [" << m_folder << ", " << deviceName << ", " << hashStr
123 << "] does not exist or not all segments are available");
124 return false;
125 }
Alexander Afanasyevdbc06712013-01-08 18:30:28 -0800126
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800127 if (!exists(file.parent_path())) {
128 create_directories(file.parent_path());
129 }
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800130
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800131 fs::ofstream off(file, std::ios::out | std::ios::binary);
132 ObjectDb fileDb(m_folder, hashStr);
Alexander Afanasyevdbc06712013-01-08 18:30:28 -0800133
134 sqlite3_int64 segment = 0;
Lijing Wang9f77a8c2016-12-25 14:44:04 -0800135 auto data = fileDb.fetchSegment(deviceName, 0);
136 while (data != nullptr) {
137 off.write(reinterpret_cast<const char*>(data->getContent().value()), data->getContent().value_size());
Alexander Afanasyevdbc06712013-01-08 18:30:28 -0800138
Lijing Wang9f77a8c2016-12-25 14:44:04 -0800139 ++segment;
140 data = fileDb.fetchSegment(deviceName, segment);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800141 }
142
Lijing Wang9f77a8c2016-12-25 14:44:04 -0800143 // permission and timestamp should be assigned somewhere else(ObjectManager has no idea about that)
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800144
Alexander Afanasyevdbc06712013-01-08 18:30:28 -0800145 return true;
146}
Lijing Wang9f77a8c2016-12-25 14:44:04 -0800147
148} // namespace chronoshare
149} // namespace ndn