├── CMakeLists.txt ├── LICENSE ├── docs ├── CMakeLists.txt ├── OpenP2P.tex ├── Root Network.tex └── UseLATEX.cmake ├── example ├── Buffer │ ├── CMakeLists.txt │ └── main.cpp ├── CMakeLists.txt ├── Crypt │ ├── CMakeLists.txt │ ├── ECDSA │ │ ├── CMakeLists.txt │ │ └── main.cpp │ └── Hash │ │ ├── CMakeLists.txt │ │ └── sha256HashExample.cpp ├── DHT │ ├── dht1.cpp │ └── dht2.cpp ├── Event │ ├── CMakeLists.txt │ └── main.cpp ├── HTTP │ ├── CMakeLists.txt │ └── mainClient.cpp ├── OFTorrent │ ├── CMakeLists.txt │ └── create.cpp ├── RPC │ ├── CMakeLists.txt │ ├── TestIdGenerator.hpp │ ├── TestRPCSocket.hpp │ ├── client.cpp │ ├── groupClient.cpp │ └── server.cpp ├── RootNetwork │ ├── CMakeLists.txt │ └── client.cpp ├── TCP │ ├── CMakeLists.txt │ ├── client.cpp │ └── server.cpp ├── Timer │ ├── CMakeLists.txt │ └── main.cpp └── UDP │ ├── CMakeLists.txt │ ├── client.cpp │ └── server.cpp ├── include └── p2p │ ├── Concurrency.hpp │ ├── Concurrency │ ├── MessageQueue.hpp │ ├── Runnable.hpp │ ├── Signal.hpp │ └── Thread.hpp │ ├── Crypt.hpp │ ├── Crypt │ ├── AES │ │ ├── CBCEncryptStream.hpp │ │ └── Key.hpp │ ├── AutoSeededRandomPool.hpp │ ├── ECDSA.hpp │ ├── ECDSA │ │ ├── Curve.hpp │ │ ├── PrivateKey.hpp │ │ ├── PublicKey.hpp │ │ ├── SignStream.hpp │ │ └── VerifyStream.hpp │ ├── Hash │ │ ├── MD5Stream.hpp │ │ └── SHA256Stream.hpp │ └── RandomPool.hpp │ ├── Event.hpp │ ├── Event │ ├── Generator.hpp │ ├── MultiGenerator.hpp │ ├── Signal.hpp │ ├── Source.hpp │ ├── Timer.hpp │ ├── UnionGenerator.hpp │ └── Wait.hpp │ ├── FolderSync │ ├── Block.hpp │ ├── BlockCache.hpp │ ├── BlockCacheMap.hpp │ ├── BlockId.hpp │ ├── BlockPath.hpp │ ├── BlockReader.hpp │ ├── BlockStore.hpp │ ├── BlockWriter.hpp │ ├── Constants.hpp │ ├── Database.hpp │ ├── Directory.hpp │ ├── FileDatabase.hpp │ ├── Journal.hpp │ ├── MemDatabase.hpp │ ├── Node.hpp │ ├── NodeBlockStore.hpp │ ├── NodeReader.hpp │ └── NodeWriter.hpp │ ├── IP.hpp │ ├── IP │ ├── Address.hpp │ ├── V4Address.hpp │ ├── V6Address.hpp │ └── Version.hpp │ ├── Kademlia.hpp │ ├── Kademlia │ ├── BucketSet.hpp │ ├── IterativeSearch.hpp │ └── SearchQueue.hpp │ ├── OFTorrent.hpp │ ├── OFTorrent │ ├── BlockStream.hpp │ ├── StreamGenerator.hpp │ └── XORStream.hpp │ ├── RPC.hpp │ ├── RPC │ ├── ChainedOperationData.hpp │ ├── Host.hpp │ ├── HostAPI.hpp │ ├── IdGenerator.hpp │ ├── Operation.hpp │ ├── OperationData.hpp │ ├── PushAPI.hpp │ └── RetrieveAPI.hpp │ ├── Root.hpp │ ├── Root │ ├── AuthenticatedSocket.hpp │ ├── ClientHost.hpp │ ├── Core │ │ ├── RPCClient.hpp │ │ ├── RPCMessage.hpp │ │ ├── RPCServer.hpp │ │ └── Service.hpp │ ├── DHT │ │ ├── RPCClient.hpp │ │ ├── RPCFindSocket.hpp │ │ ├── RPCMessage.hpp │ │ ├── RPCServer.hpp │ │ ├── ServerDelegate.hpp │ │ └── Service.hpp │ ├── Endpoint.hpp │ ├── EndpointMapSocket.hpp │ ├── Key.hpp │ ├── Message.hpp │ ├── MessageResender.hpp │ ├── NetworkId.hpp │ ├── NodeDatabase.hpp │ ├── NodeDetectSocket.hpp │ ├── NodeId.hpp │ ├── NodeInfo.hpp │ ├── NodePair.hpp │ ├── Packet.hpp │ ├── PacketSocket.hpp │ ├── Parameters.hpp │ ├── PrivateIdentity.hpp │ ├── PublicIdentity.hpp │ ├── RoutineIdGenerator.hpp │ ├── TransportSocket.hpp │ └── Types.hpp │ ├── TCP.hpp │ ├── TCP │ ├── Acceptor.hpp │ ├── Endpoint.hpp │ ├── Resolver.hpp │ └── Stream.hpp │ ├── Transport.hpp │ ├── Transport │ ├── BinaryStream.hpp │ ├── Buffer.hpp │ ├── BufferBuilder.hpp │ ├── BufferIterator.hpp │ ├── BufferedStream.hpp │ ├── FileStream.hpp │ ├── MultiplexSocket.hpp │ ├── NullStream.hpp │ ├── Socket.hpp │ ├── Stream.hpp │ └── StringStream.hpp │ ├── UDP.hpp │ ├── UDP │ ├── Endpoint.hpp │ └── Socket.hpp │ └── Util │ ├── String.hpp │ └── Timer.hpp ├── src ├── CMakeLists.txt ├── Concurrency │ ├── CMakeLists.txt │ ├── Signal.cpp │ └── Thread.cpp ├── Crypt │ ├── AutoSeededRandomPool.cpp │ ├── CMakeLists.txt │ ├── ECDSA │ │ ├── PrivateKey.cpp │ │ ├── PublicKey.cpp │ │ ├── SignStream.cpp │ │ └── VerifyStream.cpp │ └── Hash │ │ ├── MD5Stream.cpp │ │ └── SHA256Stream.cpp ├── Event │ ├── CMakeLists.txt │ ├── Generator.cpp │ ├── IOService.cpp │ ├── IOService.hpp │ ├── MultiGenerator.cpp │ ├── Signal.cpp │ ├── Source.cpp │ ├── SourceImpl.hpp │ ├── Timer.cpp │ ├── UnionGenerator.cpp │ └── Wait.cpp ├── FolderSync │ ├── Block.cpp │ ├── BlockCache.cpp │ ├── BlockCacheMap.cpp │ ├── BlockId.cpp │ ├── BlockPath.cpp │ ├── CMakeLists.txt │ ├── Directory.cpp │ ├── FileDatabase.cpp │ ├── Journal.cpp │ ├── MemDatabase.cpp │ ├── Node.cpp │ ├── NodeBlockStore.cpp │ ├── NodeReader.cpp │ └── NodeWriter.cpp ├── IP │ ├── Address.cpp │ ├── CMakeLists.txt │ ├── V4Address.cpp │ └── V6Address.cpp ├── OFTorrent │ ├── BlockStream.cpp │ ├── CMakeLists.txt │ └── XORStream.cpp ├── Root │ ├── AuthenticatedSocket.cpp │ ├── CMakeLists.txt │ ├── Core │ │ ├── RPCClient.cpp │ │ ├── RPCMessage.cpp │ │ ├── RPCServer.cpp │ │ └── Service.cpp │ ├── DHT │ │ ├── RPCClient.cpp │ │ ├── RPCFindSocket.cpp │ │ ├── RPCMessage.cpp │ │ ├── RPCServer.cpp │ │ └── Service.cpp │ ├── Endpoint.cpp │ ├── EndpointMapSocket.cpp │ ├── NetworkId.cpp │ ├── NodeDatabase.cpp │ ├── NodeDetectSocket.cpp │ ├── NodeId.cpp │ ├── NodeInfo.cpp │ ├── Packet.cpp │ ├── PacketSocket.cpp │ ├── PrivateIdentity.cpp │ ├── PublicIdentity.cpp │ ├── RoutineIdGenerator.cpp │ └── TransportSocket.cpp ├── TCP │ ├── Acceptor.cpp │ ├── CMakeLists.txt │ ├── Resolver.cpp │ └── Stream.cpp ├── Transport │ ├── BinaryStream.cpp │ ├── Buffer.cpp │ ├── BufferBuilder.cpp │ ├── BufferIterator.cpp │ ├── BufferedStream.cpp │ ├── CMakeLists.txt │ └── StringStream.cpp ├── UDP │ ├── CMakeLists.txt │ └── Socket.cpp └── Util │ ├── CMakeLists.txt │ ├── String.cpp │ └── Timer.cpp ├── tests ├── BufferTest.hpp ├── CMakeLists.txt ├── Test.cpp └── Test.hpp └── tools ├── CMakeLists.txt ├── FolderSync-FUSE ├── CMakeLists.txt ├── FUSE │ ├── CMakeLists.txt │ ├── ErrorException.hpp │ ├── FileSystem.cpp │ ├── FileSystem.hpp │ ├── Handle.hpp │ ├── Path.cpp │ └── Path.hpp ├── FileSystemWrapper.cpp ├── FileSystemWrapper.hpp ├── HandleRef.cpp ├── HandleRef.hpp ├── NodeSystem.cpp ├── NodeSystem.hpp └── main.cpp └── RootNetwork ├── CMakeLists.txt ├── Logger.cpp ├── Logger.hpp ├── networkGenerator.cpp ├── rootNetworkClient.cpp └── stringtoargcargv.cpp /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(LATEX) 2 | include(UseLATEX.cmake) 3 | add_latex_document("OpenP2P.tex" DEFAULT_PDF MANGLE_TARGET_NAMES) 4 | add_latex_document("Root Network.tex" DEFAULT_PDF MANGLE_TARGET_NAMES) 5 | -------------------------------------------------------------------------------- /example/Buffer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(bufferTest 2 | main.cpp 3 | ) 4 | 5 | target_link_libraries(bufferTest 6 | openp2p-transport 7 | openp2p-event 8 | boost_thread 9 | boost_system 10 | pthread 11 | ) 12 | 13 | -------------------------------------------------------------------------------- /example/Buffer/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | using namespace p2p; 7 | 8 | int main() { 9 | int a = -4000, b = 42, c = 1; 10 | 11 | printf("Writing (%lld, %llu, %llu) to a buffer.\n", 12 | (long long) a, 13 | (unsigned long long) b, 14 | (unsigned long long) c); 15 | 16 | Buffer buffer; 17 | BufferBuilder builder(buffer); 18 | BinaryOStream outputStream(builder); 19 | 20 | Binary::WriteInt64(outputStream, a); 21 | Binary::WriteUint32(outputStream, b); 22 | Binary::WriteUint8(outputStream, c); 23 | 24 | BufferIterator iterator(buffer); 25 | BinaryIStream inputStream(iterator); 26 | 27 | const int64_t d = Binary::ReadInt64(inputStream); 28 | const uint32_t e = Binary::ReadUint32(inputStream); 29 | const uint8_t f = Binary::ReadUint8(inputStream); 30 | 31 | printf("Read (%lld, %llu, %llu) from buffer.\n", 32 | (long long) d, 33 | (unsigned long long) e, 34 | (unsigned long long) f); 35 | 36 | return 0; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Buffer) 2 | add_subdirectory(Crypt) 3 | add_subdirectory(Event) 4 | add_subdirectory(HTTP) 5 | add_subdirectory(OFTorrent) 6 | add_subdirectory(RootNetwork) 7 | add_subdirectory(RPC) 8 | add_subdirectory(TCP) 9 | add_subdirectory(Timer) 10 | add_subdirectory(UDP) 11 | -------------------------------------------------------------------------------- /example/Crypt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(ECDSA) 2 | add_subdirectory(Hash) 3 | -------------------------------------------------------------------------------- /example/Crypt/ECDSA/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(ecdsaTest 2 | main.cpp 3 | ) 4 | 5 | target_link_libraries(ecdsaTest 6 | openp2p-crypt 7 | openp2p-transport 8 | openp2p-event 9 | boost_thread 10 | boost_system 11 | cryptopp 12 | pthread 13 | ) 14 | 15 | -------------------------------------------------------------------------------- /example/Crypt/ECDSA/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | using namespace p2p::Crypt; 7 | 8 | int main() { 9 | std::cout << "Create private key" << std::endl; 10 | 11 | AutoSeededRandomPool rand; 12 | ECDSA::PrivateKey privateKey(rand, ECDSA::brainpoolP256r1); 13 | 14 | std::cout << "Create sign stream" << std::endl; 15 | ECDSA::SignStream signStream(rand, privateKey); 16 | p2p::BinaryOStream binSign(signStream); 17 | 18 | std::cout << "Signing..." << std::endl; 19 | 20 | p2p::Binary::WriteUint32(binSign, 42); 21 | 22 | p2p::Buffer signature = signStream.signature(); 23 | 24 | std::cout << "Signed: size = " << signature.size() << " bytes" << std::endl; 25 | 26 | std::cout << "Make public key from private key" << std::endl; 27 | ECDSA::PublicKey publicKey(rand, privateKey); 28 | 29 | std::cout << "Create verify stream" << std::endl; 30 | ECDSA::VerifyStream verifyStream(publicKey, signature); 31 | p2p::BinaryOStream binVerify(verifyStream); 32 | 33 | 34 | std::cout << "Verifying..." << std::endl; 35 | 36 | p2p::Binary::WriteUint32(binVerify, 42); 37 | 38 | std::cout << "Signature is " << (verifyStream.isSignatureValid() ? "valid" : "not valid") << std::endl; 39 | 40 | return 0; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /example/Crypt/Hash/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(sha256HashExample 2 | sha256HashExample.cpp 3 | ) 4 | 5 | target_link_libraries(sha256HashExample 6 | openp2p-crypt 7 | openp2p-transport 8 | openp2p-event 9 | boost_thread 10 | boost_system 11 | cryptopp 12 | pthread 13 | ) 14 | 15 | -------------------------------------------------------------------------------- /example/Crypt/Hash/sha256HashExample.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace p2p::Crypt; 8 | 9 | int main(int argc, char *argv[]) { 10 | if (argc != 2) { 11 | printf("Usage: %s [text]\n", argv[0]); 12 | return 1; 13 | } 14 | 15 | Hash::SHA256Stream hashStream; 16 | p2p::BinaryOStream blockingStream(hashStream); 17 | 18 | const std::string text = argv[1]; 19 | 20 | printf("Input: %s\n", text.c_str()); 21 | 22 | blockingStream.writeAll((const uint8_t*) text.c_str(), text.size()); 23 | 24 | const p2p::Buffer digest = hashStream.calculateDigest(); 25 | 26 | printf("Hash length: %llu bytes\n", (unsigned long long) digest.size()); 27 | 28 | printf("Hash data: "); 29 | 30 | for (const auto v: digest) { 31 | printf("%02x", (int) v); 32 | } 33 | 34 | printf("\n\n"); 35 | 36 | return 0; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /example/DHT/dht2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | template 8 | class TestDatabase: public p2p::Kademlia::Database { 9 | public: 10 | TestDatabase() { 11 | std::cout << "Created database" << std::endl; 12 | } 13 | 14 | bool store(const p2p::Kademlia::Id& id, const p2p::Buffer& data) { 15 | std::cout << "Database store: " << id.data[0] << std::endl; 16 | return database_.store(id, data); 17 | } 18 | 19 | boost::optional retrieve(const p2p::Kademlia::Id& id) { 20 | std::cout << "Database retrieve: " << id.data[0] << std::endl; 21 | return database_.retrieve(id); 22 | } 23 | 24 | private: 25 | p2p::Kademlia::MapDatabase database_; 26 | 27 | }; 28 | 29 | typedef p2p::Kademlia::Id<1> IdType; 30 | 31 | int main() { 32 | p2p::UDP::Socket socket(46668); 33 | 34 | std::cout << "UDP socket created" << std::endl; 35 | 36 | p2p::Kademlia::IdGenerator<1> generator; 37 | 38 | std::cout << "Created ID Generator" << std::endl; 39 | 40 | p2p::RPCProtocol protocol(socket, generator); 41 | 42 | std::cout << "Created RPC Protocol" << std::endl; 43 | 44 | TestDatabase<1> database; 45 | 46 | std::cout << "Created database" << std::endl; 47 | 48 | IdType myId; 49 | myId.data[0] = 'B'; 50 | 51 | p2p::Kademlia::DHT dht(protocol, myId, database); 52 | 53 | std::cout << "Created DHT" << std::endl; 54 | 55 | char s[1]; 56 | 57 | std::cin.getline(s, 1); 58 | 59 | std::cout << "Got line" << std::endl; 60 | 61 | return 0; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /example/Event/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(eventTest 2 | main.cpp 3 | ) 4 | 5 | target_link_libraries(eventTest 6 | openp2p-concurrency 7 | openp2p-event 8 | boost_thread 9 | boost_system 10 | pthread 11 | ) 12 | -------------------------------------------------------------------------------- /example/Event/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace p2p; 9 | 10 | #define COLOR_RESET "\x1B[0m" 11 | #define COLOR_RED "\x1B[31m" 12 | #define COLOR_GREEN "\x1B[32m" 13 | #define COLOR_YELLOW "\x1B[33m" 14 | #define COLOR_BLUE "\x1B[34m" 15 | #define COLOR_MAGENTA "\x1B[35m" 16 | #define COLOR_CYAN "\x1B[36m" 17 | #define COLOR_WHITE "\x1B[37m" 18 | 19 | class EventThreadRunnable: public Runnable { 20 | public: 21 | EventThreadRunnable() { } 22 | virtual ~EventThreadRunnable() { } 23 | 24 | struct SetToFalse { 25 | bool& v; 26 | SetToFalse(bool& pV) : v(pV) { } 27 | ~SetToFalse() { 28 | v = false; 29 | } 30 | }; 31 | 32 | void activate() { 33 | printf(COLOR_BLUE "Activate!\n" COLOR_RESET); 34 | 35 | eventGenerator_.activate(); 36 | } 37 | 38 | void sleepFor(size_t secs) { 39 | while (secs > 0) { 40 | printf(COLOR_BLUE "%llu secs...\n" COLOR_RESET, (unsigned long long) secs); 41 | sleep(1); 42 | secs -= 1; 43 | } 44 | } 45 | 46 | void run() { 47 | SetToFalse setToFalse(isRunning_); 48 | 49 | activate(); 50 | 51 | sleepFor(2); 52 | 53 | activate(); 54 | 55 | sleepFor(5); 56 | 57 | activate(); 58 | 59 | sleepFor(2); 60 | 61 | activate(); 62 | } 63 | 64 | Event::Source eventSource() { 65 | return eventGenerator_.eventSource(); 66 | } 67 | 68 | void cancel() { } 69 | 70 | bool isRunning() const { 71 | return isRunning_; 72 | } 73 | 74 | private: 75 | bool isRunning_; 76 | Event::Generator eventGenerator_; 77 | 78 | }; 79 | 80 | int main() { 81 | EventThreadRunnable eventThreadRunnable; 82 | 83 | Thread thread(eventThreadRunnable); 84 | 85 | printf(COLOR_GREEN "--- Started.\n" COLOR_RESET); 86 | 87 | while (eventThreadRunnable.isRunning()) { 88 | printf(COLOR_GREEN "--- Waiting...\n" COLOR_RESET); 89 | Event::Wait(std::vector(1, eventThreadRunnable.eventSource())); 90 | printf(COLOR_GREEN "--- Event received.\n" COLOR_RESET); 91 | sleep(3); 92 | } 93 | 94 | printf(COLOR_GREEN "--- Done.\n" COLOR_RESET); 95 | 96 | return 0; 97 | } 98 | 99 | -------------------------------------------------------------------------------- /example/HTTP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(httpClient 2 | mainClient.cpp 3 | ) 4 | 5 | target_link_libraries(httpClient 6 | openp2p-tcp 7 | openp2p-ip 8 | openp2p-concurrency 9 | openp2p-transport 10 | openp2p-event 11 | openp2p-util 12 | boost_thread 13 | boost_system 14 | pthread 15 | ) 16 | 17 | -------------------------------------------------------------------------------- /example/OFTorrent/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(oftorrent_create 2 | create.cpp 3 | ) 4 | 5 | target_link_libraries(oftorrent_create 6 | openp2p-oftorrent 7 | openp2p-transport 8 | openp2p-event 9 | boost_system 10 | boost_thread 11 | pthread 12 | ) 13 | 14 | -------------------------------------------------------------------------------- /example/OFTorrent/create.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | using namespace p2p; 8 | 9 | class BlockGen: public OFTorrent::OutputStreamGenerator { 10 | public: 11 | BlockGen() : count_(0) { } 12 | 13 | OStream& getNextOutputStream() { 14 | std::ostringstream s; 15 | s << "out" << count_ << ".txt"; 16 | count_++; 17 | fileStream.open(s.str()); 18 | return fileStream; 19 | } 20 | 21 | private: 22 | size_t count_; 23 | FileOStream fileStream; 24 | 25 | }; 26 | 27 | int main(int argc, char* argv[]) { 28 | if (argc != 2) { 29 | std::cout << "create [filename]" << std::endl; 30 | return 0; 31 | } 32 | 33 | FileIStream fileStream(argv[1]); 34 | 35 | if (!fileStream.isOpen()) { 36 | std::cout << "Failed to open file" << std::endl; 37 | } 38 | 39 | NullIStream nullStream; 40 | 41 | OFTorrent::XORStream xorStream(fileStream, nullStream); 42 | 43 | BlockGen blockGen; 44 | 45 | OFTorrent::BlockStream blockStream(blockGen, OFTorrent::BLOCKSIZE_512KB); 46 | 47 | Binary::MoveData(xorStream, blockStream); 48 | 49 | return 0; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /example/RPC/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # add_executable(rpcClient client.cpp) 2 | # add_executable(rpcGroupClient groupClient.cpp) 3 | # add_executable(rpcServer server.cpp) 4 | # target_link_libraries(rpcClient boost_thread boost_system openp2p openp2p-udp) 5 | # target_link_libraries(rpcGroupClient boost_thread boost_system openp2p openp2p-udp) 6 | # target_link_libraries(rpcServer boost_thread boost_system openp2p openp2p-udp) 7 | -------------------------------------------------------------------------------- /example/RPC/TestIdGenerator.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class TestIdGenerator: public p2p::IdGenerator { 4 | public: 5 | TestIdGenerator() : id_(0) { } 6 | 7 | uint32_t generate() { 8 | return id_++; 9 | } 10 | 11 | private: 12 | uint32_t id_; 13 | 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /example/RPC/TestRPCSocket.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace p2p; 6 | 7 | class TestRPCSocket: public RPC::Socket { 8 | public: 9 | TestRPCSocket(UDP::Socket& socket) : socket_(socket) { } 10 | 11 | void send(const IP::Endpoint& endpoint, bool isRequest, const uint32_t& id, const Buffer& data) { 12 | Buffer buffer; 13 | BufferBuilder builder(buffer); 14 | BinaryOStream stream(builder); 15 | stream << isRequest << id << data; 16 | 17 | socket_.send(endpoint, buffer); 18 | } 19 | 20 | bool receive(IP::Endpoint& endpoint, bool& isRequest, uint32_t& id, Buffer& data) { 21 | Buffer buff; 22 | 23 | if (socket_.receive(endpoint, buff)) { 24 | BufferIterator iterator(buff); 25 | BinaryIStream stream(iterator); 26 | return (stream >> isRequest >> id >> data); 27 | } else { 28 | return false; 29 | } 30 | } 31 | 32 | void cancel() { 33 | // 34 | } 35 | 36 | void close() { 37 | socket_.close(); 38 | } 39 | 40 | private: 41 | UDP::Socket& socket_; 42 | 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /example/RPC/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "TestIdGenerator.hpp" 8 | #include "TestRPCSocket.hpp" 9 | 10 | int main() { 11 | UDP::Socket socket; 12 | TestRPCSocket rpcSocket(socket); 13 | TestIdGenerator idGenerator; 14 | 15 | RPC::Protocol rpcProtocol(rpcSocket, idGenerator); 16 | 17 | Buffer buffer; 18 | BufferBuilder builder(buffer); 19 | BinaryOStream buildStream(builder); 20 | std::string message("Hello from client"); 21 | buildStream << message; 22 | 23 | RPC::Call call(rpcProtocol, UDP::Endpoint(boost::asio::ip::address_v4::loopback(), 45557), buffer); 24 | 25 | boost::optional reply = call.execute(); 26 | 27 | if (reply) { 28 | BufferIterator iterator(*reply); 29 | BinaryIStream stream(iterator); 30 | std::string string(17, 0); 31 | stream >> string; 32 | 33 | std::cout << "Got reply: " << string << std::endl; 34 | } else { 35 | std::cout << "Failed to get reply" << std::endl; 36 | } 37 | 38 | return 0; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /example/RPC/groupClient.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "TestIdGenerator.hpp" 8 | #include "TestRPCSocket.hpp" 9 | 10 | int main() { 11 | const unsigned int num = 500; 12 | 13 | UDP::Socket socket; 14 | TestRPCSocket rpcSocket(socket); 15 | TestIdGenerator idGenerator; 16 | 17 | RPC::Protocol rpcProtocol(rpcSocket, idGenerator); 18 | 19 | RPC::Group rpcGroup(rpcProtocol); 20 | 21 | Buffer buffer; 22 | BufferBuilder builder(buffer); 23 | BinaryOStream buildStream(builder); 24 | std::string message("Hello from group!"); 25 | buildStream << message; 26 | 27 | for (unsigned int i = 0; i < num; i++) { 28 | rpcGroup.add(UDP::Endpoint(boost::asio::ip::address_v4::loopback(), 45557), buffer); 29 | } 30 | 31 | rpcGroup.execute(); 32 | 33 | for (unsigned int i = 0; i < num; i++) { 34 | if (rpcGroup.hasReply(i)) { 35 | BufferIterator iterator(rpcGroup.getReply(i)); 36 | BinaryIStream stream(iterator); 37 | std::string string(17, 0); 38 | stream >> string; 39 | 40 | std::cout << "Got reply(" << i << "): " << string << std::endl; 41 | } else { 42 | std::cout << "Failed to get reply(" << i << ")" << std::endl; 43 | } 44 | } 45 | 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /example/RPC/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "TestIdGenerator.hpp" 8 | #include "TestRPCSocket.hpp" 9 | 10 | int main() { 11 | UDP::Socket socket(45557); 12 | TestRPCSocket rpcSocket(socket); 13 | TestIdGenerator idGenerator; 14 | 15 | RPC::Protocol protocol(rpcSocket, idGenerator); 16 | 17 | uint32_t rpcId; 18 | UDP::Endpoint endpoint; 19 | Buffer buffer; 20 | 21 | unsigned int count = 0; 22 | 23 | while (protocol.receiveRequest(endpoint, rpcId, buffer)) { 24 | BufferIterator iterator(buffer); 25 | BinaryIStream stream(iterator); 26 | std::string string(17, 0); 27 | stream >> string; 28 | 29 | std::cout << "Message(" << count << ") " << rpcId << ": " << string << std::endl; 30 | count++; 31 | 32 | Buffer buffer; 33 | BufferBuilder builder(buffer); 34 | BinaryOStream buildStream(builder); 35 | std::string message("Hello from server"); 36 | buildStream << message; 37 | 38 | protocol.sendReply(endpoint, rpcId, buffer); 39 | } 40 | 41 | return 0; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /example/RootNetwork/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(client 2 | client.cpp 3 | ) 4 | 5 | target_link_libraries(client 6 | openp2p-rootnetwork 7 | openp2p-udp 8 | openp2p-ip 9 | openp2p-crypt 10 | openp2p-concurrency 11 | openp2p-transport 12 | openp2p-event 13 | openp2p-util 14 | boost_thread 15 | boost_system 16 | cryptopp 17 | pthread 18 | ) 19 | 20 | -------------------------------------------------------------------------------- /example/TCP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(tcpClient 2 | client.cpp 3 | ) 4 | 5 | add_executable(tcpServer 6 | server.cpp 7 | ) 8 | 9 | target_link_libraries(tcpClient 10 | openp2p-tcp 11 | openp2p-ip 12 | openp2p-transport 13 | openp2p-event 14 | openp2p-util 15 | boost_thread 16 | boost_system 17 | pthread 18 | ) 19 | 20 | target_link_libraries(tcpServer 21 | openp2p-tcp 22 | openp2p-ip 23 | openp2p-transport 24 | openp2p-concurrency 25 | openp2p-event 26 | openp2p-util 27 | boost_thread 28 | boost_system 29 | pthread) 30 | -------------------------------------------------------------------------------- /example/TCP/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | int main() { 8 | using namespace p2p; 9 | 10 | TCP::Stream tcpStream; 11 | std::cout << "---Connecting" << std::endl; 12 | 13 | if (!tcpStream.connect(TCP::Endpoint(IP::V4Address::Localhost(), 45556))) { 14 | std::cout << "---Failed to connect" << std::endl; 15 | return 0; 16 | } 17 | 18 | std::cout << "---Successfully connected" << std::endl; 19 | 20 | BinaryIOStream stream(tcpStream); 21 | 22 | for (unsigned int i = 0; i < 1000; i += 2) { 23 | Binary::WriteUint32(stream.output(), i); 24 | 25 | std::cout << "Sent: " << i << std::endl; 26 | 27 | const uint32_t v = Binary::ReadUint32(stream.input()); 28 | 29 | if (v != (i + 1)) { 30 | std::cout << "Wrong number: " << v << ", Expected: " << (i + 1) << std::endl; 31 | return 0; 32 | } else { 33 | std::cout << "Received: " << v << std::endl; 34 | } 35 | } 36 | 37 | std::cout << "---Successfully completed transfer" << std::endl; 38 | 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /example/Timer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(timerTest main.cpp) 2 | 3 | target_link_libraries(timerTest 4 | openp2p-event 5 | boost_thread 6 | boost_system 7 | pthread 8 | ) 9 | -------------------------------------------------------------------------------- /example/Timer/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | int main() { 7 | p2p::Event::Timer timer5Secs, timer10Secs; 8 | timer5Secs.setMilliseconds(5000); 9 | timer10Secs.setMilliseconds(10000); 10 | 11 | timer5Secs.schedule(); 12 | timer10Secs.schedule(); 13 | 14 | while (true) { 15 | const bool wasExpired5Secs = timer5Secs.hasExpired(), wasExpired10Secs = timer10Secs.hasExpired(); 16 | if (wasExpired5Secs && wasExpired10Secs) break; 17 | 18 | p2p::Event::Wait({ timer5Secs.eventSource(), timer10Secs.eventSource() }); 19 | 20 | if (!wasExpired5Secs && timer5Secs.hasExpired()) { 21 | printf("5 second timer has expired!\n"); 22 | } 23 | 24 | if (!wasExpired10Secs && timer10Secs.hasExpired()) { 25 | printf("10 second timer has expired!\n"); 26 | } 27 | } 28 | 29 | return 0; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /example/UDP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(udpClient 2 | client.cpp 3 | ) 4 | 5 | add_executable(udpServer 6 | server.cpp 7 | ) 8 | 9 | target_link_libraries(udpClient 10 | openp2p-udp 11 | openp2p-ip 12 | openp2p-transport 13 | openp2p-event 14 | openp2p-util 15 | boost_thread 16 | boost_system 17 | pthread 18 | ) 19 | 20 | target_link_libraries(udpServer 21 | openp2p-udp 22 | openp2p-ip 23 | openp2p-transport 24 | openp2p-event 25 | openp2p-util 26 | boost_thread 27 | boost_system 28 | pthread) 29 | -------------------------------------------------------------------------------- /example/UDP/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace p2p; 9 | 10 | int main() { 11 | printf("UDP Client Started.\n"); 12 | 13 | UDP::Socket socket; 14 | 15 | { 16 | Buffer buffer; 17 | BufferBuilder builder(buffer); 18 | BinaryOStream binaryStream(builder); 19 | Binary::WriteUint16(binaryStream, 0); 20 | socket.send(UDP::Endpoint(IP::V6Address::Localhost(), 45557), buffer); 21 | 22 | printf("Sent: 0\n"); 23 | } 24 | 25 | uint16_t expectedValue = 1; 26 | 27 | while (true) { 28 | UDP::Endpoint endpoint; 29 | Buffer data; 30 | 31 | while (!socket.receive(endpoint, data)) { 32 | if (!socket.isValid()) { 33 | printf("Socket became invalid.\n"); 34 | return -1; 35 | } 36 | 37 | Event::Wait({ socket.eventSource() }); 38 | } 39 | 40 | BufferIterator iterator(data); 41 | BinaryIStream blockingReader(iterator); 42 | const uint16_t i = Binary::ReadUint16(blockingReader); 43 | 44 | printf("Received: %u from '%s'.\n", 45 | (unsigned) i, endpoint.toString().c_str()); 46 | 47 | if (i != expectedValue) { 48 | printf("Incorrect data received: %u.\n", (unsigned) i); 49 | return -1; 50 | } 51 | 52 | if (i >= 9999) { 53 | printf("Completed successfully.\n"); 54 | return 0; 55 | } 56 | 57 | Buffer buffer; 58 | BufferBuilder builder(buffer); 59 | BinaryOStream blockingWriter(builder); 60 | Binary::WriteUint16(blockingWriter, i + 1); 61 | socket.send(endpoint, buffer); 62 | 63 | printf("Sent: %u.\n", (unsigned) (i + 1)); 64 | 65 | expectedValue += 2; 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /example/UDP/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace p2p; 11 | 12 | int main() { 13 | UDP::Socket socket(45557); 14 | 15 | std::map expectedValueMap; 16 | 17 | printf("UDP Server Started.\n"); 18 | 19 | while (socket.isValid()) { 20 | UDP::Endpoint endpoint; 21 | Buffer data; 22 | 23 | if (!socket.receive(endpoint, data)) { 24 | Event::Wait({ socket.eventSource() }); 25 | continue; 26 | } 27 | 28 | uint16_t& expectedValue = expectedValueMap[endpoint]; 29 | 30 | BufferIterator iterator(data); 31 | BinaryIStream blockingReader(iterator); 32 | const uint16_t i = Binary::ReadUint16(blockingReader); 33 | 34 | printf("Received: %u from '%s'.\n", 35 | (unsigned) i, endpoint.toString().c_str()); 36 | 37 | if (i != expectedValue) { 38 | printf("Incorrect data received: %u from endpoint '%s'.\n", 39 | (unsigned) i, endpoint.toString().c_str()); 40 | expectedValue = 0; 41 | continue; 42 | } 43 | 44 | if (i >= 9999) { 45 | printf("Completed successfully for endpoint '%s'.\n", 46 | endpoint.toString().c_str()); 47 | expectedValue = 0; 48 | continue; 49 | } 50 | 51 | Buffer buffer; 52 | BufferBuilder builder(buffer); 53 | BinaryOStream blockingWriter(builder); 54 | Binary::WriteUint16(blockingWriter, i + 1); 55 | socket.send(endpoint, buffer); 56 | 57 | printf("Sent: %u.\n", (unsigned) (i + 1)); 58 | 59 | expectedValue += 2; 60 | } 61 | 62 | return 0; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /include/p2p/Concurrency.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | -------------------------------------------------------------------------------- /include/p2p/Concurrency/MessageQueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CONCURRENCY_MESSAGEQUEUE_HPP 2 | #define P2P_CONCURRENCY_MESSAGEQUEUE_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace p2p { 11 | 12 | template 13 | class MessageQueue { 14 | public: 15 | MessageQueue() { } 16 | 17 | Event::Source eventSource() const { 18 | return signal_.eventSource(); 19 | } 20 | 21 | bool empty() const { 22 | std::lock_guard lock(mutex_); 23 | return queue_.empty(); 24 | } 25 | 26 | T receive() { 27 | std::lock_guard lock(mutex_); 28 | auto message = std::move(queue_.front()); 29 | queue_.pop(); 30 | return message; 31 | } 32 | 33 | void send(T message) { 34 | std::lock_guard lock(mutex_); 35 | queue_.push(std::move(message)); 36 | signal_.activate(); 37 | } 38 | 39 | private: 40 | mutable std::mutex mutex_; 41 | std::queue queue_; 42 | Event::Signal signal_; 43 | 44 | }; 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/p2p/Concurrency/Runnable.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CONCURRENCY_RUNNABLE_HPP 2 | #define P2P_CONCURRENCY_RUNNABLE_HPP 3 | 4 | namespace p2p { 5 | 6 | namespace Concurrency { 7 | 8 | class Runnable { 9 | public: 10 | virtual void run() = 0; 11 | 12 | virtual void cancel() = 0; 13 | 14 | }; 15 | 16 | } 17 | 18 | using Runnable = Concurrency::Runnable; 19 | 20 | } 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/p2p/Concurrency/Signal.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CONCURRENCY_SIGNAL_HPP 2 | #define P2P_CONCURRENCY_SIGNAL_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | class Signal { 10 | public: 11 | Signal(); 12 | 13 | void activate(); 14 | 15 | void reset(); 16 | 17 | bool isActivated() const; 18 | 19 | void wait(); 20 | 21 | void cancel(); 22 | 23 | private: 24 | // Non-copyable. 25 | Signal(const Signal&) = delete; 26 | Signal& operator=(const Signal&) = delete; 27 | 28 | mutable std::mutex mutex_; 29 | std::condition_variable condition_; 30 | bool isActivated_; 31 | 32 | }; 33 | 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/p2p/Concurrency/Thread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CONCURRENCY_THREAD_HPP 2 | #define P2P_CONCURRENCY_THREAD_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace p2p { 9 | 10 | namespace Concurrency { 11 | 12 | class Thread { 13 | public: 14 | Thread(); 15 | Thread(Runnable& runnable); 16 | Thread(Thread&&); 17 | Thread& operator=(Thread&&); 18 | 19 | ~Thread(); 20 | 21 | private: 22 | // Non-copyable. 23 | Thread(const Thread&) = delete; 24 | Thread& operator=(Thread) = delete; 25 | 26 | std::unique_ptr impl_; 27 | 28 | }; 29 | 30 | } 31 | 32 | using Thread = Concurrency::Thread; 33 | 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/p2p/Crypt.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | -------------------------------------------------------------------------------- /include/p2p/Crypt/AES/CBCEncryptStream.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scrossuk/openp2p/07c29cf96c72748ddc1748488b45f73b100f0c62/include/p2p/Crypt/AES/CBCEncryptStream.hpp -------------------------------------------------------------------------------- /include/p2p/Crypt/AES/Key.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_AES_KEY_HPP 2 | #define P2P_CRYPT_AES_KEY_HPP 3 | 4 | namespace p2p { 5 | 6 | namespace Crypt { 7 | 8 | namespace AES { 9 | 10 | enum KeySize { 11 | KEYSIZE_128BITS = 16, 12 | KEYSIZE_192BITS = 24, 13 | KEYSIZE_256BITS = 32 14 | }; 15 | 16 | template 17 | class Key; 18 | 19 | } 20 | 21 | } 22 | 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/p2p/Crypt/AutoSeededRandomPool.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_AUTOSEEDEDRANDOMPOOL_HPP 2 | #define P2P_CRYPT_AUTOSEEDEDRANDOMPOOL_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace Crypt { 14 | 15 | class AutoSeededRandomPool: public RandomPool { 16 | public: 17 | void generateBlock(uint8_t* data, size_t size); 18 | 19 | operator CryptoPP::RandomPool& (); 20 | 21 | private: 22 | CryptoPP::AutoSeededRandomPool randPool_; 23 | 24 | }; 25 | 26 | } 27 | 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/p2p/Crypt/ECDSA.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | -------------------------------------------------------------------------------- /include/p2p/Crypt/ECDSA/Curve.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_ECDSA_CURVE_HPP 2 | #define P2P_CRYPT_ECDSA_CURVE_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace Crypt { 9 | 10 | namespace ECDSA { 11 | 12 | enum Curve { 13 | brainpoolP256r1, 14 | brainpoolP512r1 15 | }; 16 | 17 | } 18 | 19 | } 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/p2p/Crypt/ECDSA/PrivateKey.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_ECDSA_PRIVATEKEY_HPP 2 | #define P2P_CRYPT_ECDSA_PRIVATEKEY_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace Crypt { 13 | 14 | class RandomPool; 15 | 16 | namespace ECDSA { 17 | 18 | class PrivateKey { 19 | public: 20 | PrivateKey(); 21 | PrivateKey(RandomPool& pool, Curve curve); 22 | 23 | operator CryptoPP::ECDSA::PrivateKey& (); 24 | 25 | operator const CryptoPP::ECDSA::PrivateKey& () const; 26 | 27 | private: 28 | CryptoPP::ECDSA::PrivateKey privateKey_; 29 | 30 | }; 31 | 32 | } 33 | 34 | } 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/p2p/Crypt/ECDSA/PublicKey.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_ECDSA_PUBLICKEY_HPP 2 | #define P2P_CRYPT_ECDSA_PUBLICKEY_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace Crypt { 13 | 14 | class RandomPool; 15 | 16 | namespace ECDSA { 17 | 18 | class PrivateKey; 19 | 20 | class PublicKey { 21 | public: 22 | PublicKey(); 23 | PublicKey(RandomPool& pool, const PrivateKey& privateKey); 24 | 25 | static PublicKey FromBuffer(const Buffer& buffer); 26 | 27 | Buffer toBuffer() const; 28 | 29 | operator CryptoPP::ECDSA::PublicKey& (); 30 | 31 | operator const CryptoPP::ECDSA::PublicKey& () const; 32 | 33 | private: 34 | CryptoPP::ECDSA::PublicKey key_; 35 | 36 | }; 37 | 38 | } 39 | 40 | } 41 | 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/p2p/Crypt/ECDSA/SignStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_ECDSA_SIGNSTREAM_HPP 2 | #define P2P_CRYPT_ECDSA_SIGNSTREAM_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace Crypt { 14 | 15 | class RandomPool; 16 | 17 | namespace ECDSA { 18 | 19 | class PrivateKey; 20 | 21 | class SignStream: public OStream { 22 | public: 23 | SignStream(RandomPool& pool, const PrivateKey& privateKey); 24 | ~SignStream(); 25 | 26 | bool isValid() const; 27 | 28 | Event::Source eventSource() const; 29 | 30 | size_t write(const uint8_t* data, size_t size); 31 | 32 | Buffer signature(); 33 | 34 | private: 35 | SignStream(const SignStream&) = delete; 36 | SignStream& operator=(SignStream) = delete; 37 | 38 | std::unique_ptr impl_; 39 | 40 | }; 41 | 42 | } 43 | 44 | } 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/p2p/Crypt/ECDSA/VerifyStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_ECDSA_VERIFYSTREAM_HPP 2 | #define P2P_CRYPT_ECDSA_VERIFYSTREAM_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace Crypt { 14 | 15 | namespace ECDSA { 16 | 17 | class PublicKey; 18 | 19 | class VerifyStream: public OStream { 20 | public: 21 | VerifyStream(const PublicKey& publicKey, const Buffer& signature); 22 | ~VerifyStream(); 23 | 24 | bool isValid() const; 25 | 26 | Event::Source eventSource() const; 27 | 28 | size_t write(const uint8_t* data, size_t size); 29 | 30 | bool isSignatureValid(); 31 | 32 | private: 33 | VerifyStream(const VerifyStream&) = delete; 34 | VerifyStream& operator=(VerifyStream) = delete; 35 | 36 | std::unique_ptr impl_; 37 | 38 | }; 39 | 40 | } 41 | 42 | } 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/p2p/Crypt/Hash/MD5Stream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_HASH_MD5STREAM_HPP 2 | #define P2P_CRYPT_HASH_MD5STREAM_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace Crypt { 14 | 15 | namespace Hash { 16 | 17 | /** 18 | * \brief MD5 Stream 19 | * 20 | * Note that the MD5 algorithm is now considered 21 | * unsuitable for security purposes; this should 22 | * be used for applications where hash security 23 | * is not required. 24 | */ 25 | class MD5Stream: public OStream { 26 | public: 27 | MD5Stream(); 28 | ~MD5Stream(); 29 | 30 | bool isValid() const; 31 | 32 | Event::Source eventSource() const; 33 | 34 | size_t write(const uint8_t* data, size_t size); 35 | 36 | Buffer calculateDigest(); 37 | 38 | private: 39 | // Non-copyable. 40 | MD5Stream(const MD5Stream&) = delete; 41 | MD5Stream& operator=(MD5Stream) = delete; 42 | 43 | std::unique_ptr impl_; 44 | 45 | }; 46 | 47 | } 48 | 49 | } 50 | 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/p2p/Crypt/Hash/SHA256Stream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_HASH_SHA256STREAM_HPP 2 | #define P2P_CRYPT_HASH_SHA256STREAM_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace Crypt { 14 | 15 | namespace Hash { 16 | 17 | class SHA256Stream: public OStream { 18 | public: 19 | SHA256Stream(); 20 | ~SHA256Stream(); 21 | 22 | bool isValid() const; 23 | 24 | Event::Source eventSource() const; 25 | 26 | size_t write(const uint8_t* data, size_t size); 27 | 28 | Buffer calculateDigest(); 29 | 30 | private: 31 | // Non-copyable. 32 | SHA256Stream(const SHA256Stream&) = delete; 33 | SHA256Stream& operator=(SHA256Stream) = delete; 34 | 35 | std::unique_ptr impl_; 36 | 37 | }; 38 | 39 | } 40 | 41 | } 42 | 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /include/p2p/Crypt/RandomPool.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_CRYPT_RANDOMPOOL_HPP 2 | #define P2P_CRYPT_RANDOMPOOL_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace p2p { 10 | 11 | namespace Crypt { 12 | 13 | class RandomPool { 14 | public: 15 | virtual void generateBlock(uint8_t* data, size_t size) = 0; 16 | 17 | virtual operator CryptoPP::RandomPool& () = 0; 18 | 19 | }; 20 | 21 | } 22 | 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/p2p/Event.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | -------------------------------------------------------------------------------- /include/p2p/Event/Generator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_EVENT_GENERATOR_HPP 2 | #define P2P_EVENT_GENERATOR_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace Event { 9 | 10 | class Source; 11 | 12 | class Generator { 13 | public: 14 | Generator(bool initialState = false); 15 | ~Generator(); 16 | 17 | // Moveable. 18 | Generator(Generator&& other); 19 | Generator& operator=(Generator&&); 20 | 21 | void activate(); 22 | 23 | Source eventSource() const; 24 | 25 | private: 26 | // Non-copyable. 27 | Generator(const Generator&) = delete; 28 | Generator& operator=(const Generator&) = delete; 29 | 30 | std::unique_ptr impl_; 31 | 32 | }; 33 | 34 | } 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/p2p/Event/MultiGenerator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_EVENT_MULTIGENERATOR_HPP 2 | #define P2P_EVENT_MULTIGENERATOR_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace Event { 9 | 10 | class Source; 11 | 12 | class MultiGenerator { 13 | public: 14 | MultiGenerator(Source source); 15 | ~MultiGenerator(); 16 | 17 | size_t addClient(); 18 | 19 | void removeClient(size_t clientId); 20 | 21 | Source eventSource(size_t clientId) const; 22 | 23 | private: 24 | // Non-copyable. 25 | MultiGenerator(const MultiGenerator&) = delete; 26 | MultiGenerator& operator=(MultiGenerator) = delete; 27 | 28 | std::unique_ptr impl_; 29 | 30 | }; 31 | 32 | } 33 | 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/p2p/Event/Signal.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_EVENT_SIGNAL_HPP 2 | #define P2P_EVENT_SIGNAL_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace p2p { 9 | 10 | namespace Event { 11 | 12 | class Signal { 13 | public: 14 | Signal(); 15 | ~Signal(); 16 | 17 | // Moveable. 18 | Signal(Signal&& other); 19 | Signal& operator=(Signal&&); 20 | 21 | void activate(); 22 | 23 | void reset(); 24 | 25 | bool isActive() const; 26 | 27 | Source eventSource() const; 28 | 29 | private: 30 | // Non-copyable. 31 | Signal(const Signal&) = delete; 32 | Signal& operator=(const Signal&) = delete; 33 | 34 | std::unique_ptr impl_; 35 | 36 | }; 37 | 38 | } 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/p2p/Event/Source.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_EVENT_SOURCE_HPP 2 | #define P2P_EVENT_SOURCE_HPP 3 | 4 | namespace p2p { 5 | 6 | namespace Event { 7 | 8 | class SourceImpl; 9 | 10 | class Source { 11 | public: 12 | Source(); 13 | Source(SourceImpl*); 14 | 15 | SourceImpl* impl(); 16 | 17 | private: 18 | SourceImpl* impl_; 19 | 20 | }; 21 | 22 | } 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/p2p/Event/Timer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_EVENT_TIMER_HPP 2 | #define P2P_EVENT_TIMER_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace Event { 9 | 10 | class Source; 11 | 12 | class Timer { 13 | public: 14 | Timer(); 15 | ~Timer(); 16 | 17 | // Moveable. 18 | Timer(Timer&& other); 19 | Timer& operator=(Timer&&); 20 | 21 | void setMilliseconds(double milliseconds); 22 | 23 | void schedule(); 24 | 25 | bool hasExpired() const; 26 | 27 | Source eventSource() const; 28 | 29 | private: 30 | // Non-copyable. 31 | Timer(const Timer&) = delete; 32 | Timer& operator=(const Timer&) = delete; 33 | 34 | std::unique_ptr impl_; 35 | 36 | }; 37 | 38 | } 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/p2p/Event/UnionGenerator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_EVENT_UNIONGENERATOR_HPP 2 | #define P2P_EVENT_UNIONGENERATOR_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace Event { 10 | 11 | class Source; 12 | 13 | class UnionGenerator { 14 | public: 15 | UnionGenerator(std::vector sourceList); 16 | ~UnionGenerator(); 17 | 18 | Source eventSource() const; 19 | 20 | private: 21 | // Non-copyable. 22 | UnionGenerator(const UnionGenerator&) = delete; 23 | UnionGenerator& operator=(UnionGenerator) = delete; 24 | 25 | std::unique_ptr impl_; 26 | 27 | }; 28 | 29 | } 30 | 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/p2p/Event/Wait.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_EVENT_WAIT_HPP 2 | #define P2P_EVENT_WAIT_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace p2p { 9 | 10 | namespace Event { 11 | 12 | void Wait(const std::vector& sources); 13 | 14 | } 15 | 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/Block.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_BLOCK_HPP 2 | #define P2P_FOLDERSYNC_BLOCK_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace FolderSync { 13 | 14 | // Get number of blocks required to store a given number of bytes. 15 | inline size_t BYTES_TO_BLOCKS(size_t bytes) { 16 | return (bytes + (BLOCK_SIZE - 1)) / BLOCK_SIZE; 17 | } 18 | 19 | class Block { 20 | public: 21 | static Block Zero(); 22 | 23 | Block(Block&& block) noexcept; 24 | 25 | uint8_t* data(); 26 | 27 | const uint8_t* data() const; 28 | 29 | size_t size() const; 30 | 31 | Block copy() const; 32 | 33 | private: 34 | Block(); 35 | 36 | // Non-copyable. 37 | Block(const Block&) = delete; 38 | Block& operator=(Block) = delete; 39 | 40 | std::vector data_; 41 | 42 | }; 43 | 44 | } 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/BlockCache.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_BLOCKCACHE_HPP 2 | #define P2P_FOLDERSYNC_BLOCKCACHE_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace FolderSync { 9 | 10 | class Block; 11 | class BlockPath; 12 | class BlockStore; 13 | 14 | class BlockCache { 15 | public: 16 | BlockCache(BlockStore& blockStore); 17 | ~BlockCache(); 18 | 19 | const Block& getReadBlock(const BlockPath& path) const; 20 | 21 | Block& getWriteBlock(const BlockPath& path); 22 | 23 | void flush(); 24 | 25 | private: 26 | // Non-copyable. 27 | BlockCache(const BlockCache&) = delete; 28 | BlockCache& operator=(BlockCache) = delete; 29 | 30 | mutable BlockCacheMap map_; 31 | 32 | }; 33 | 34 | } 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/BlockCacheMap.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_BLOCKCACHEMAP_HPP 2 | #define P2P_FOLDERSYNC_BLOCKCACHEMAP_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace FolderSync { 14 | 15 | class BlockStore; 16 | 17 | struct BlockInfo { 18 | bool isDirty; 19 | size_t childCount; 20 | Block block; 21 | 22 | inline BlockInfo(Block&& pBlock) 23 | : isDirty(false), 24 | childCount(0), 25 | block(std::move(pBlock)) { } 26 | }; 27 | 28 | class BlockCacheMap { 29 | public: 30 | BlockCacheMap(BlockStore& blockStore); 31 | 32 | BlockInfo& loadBlock(const BlockPath& path); 33 | 34 | void evictVictim(); 35 | 36 | void flush(); 37 | 38 | private: 39 | // Non-copyable. 40 | BlockCacheMap(const BlockCacheMap&) = delete; 41 | BlockCacheMap& operator=(BlockCacheMap) = delete; 42 | 43 | BlockStore& blockStore_; 44 | std::unordered_map blockMap_; 45 | 46 | }; 47 | 48 | } 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/BlockId.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_BLOCKID_HPP 2 | #define P2P_FOLDERSYNC_BLOCKID_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace FolderSync { 17 | 18 | class BlockId { 19 | public: 20 | BlockId(); 21 | 22 | static BlockId Zero(); 23 | static BlockId FromReader(BlockingReader& reader); 24 | 25 | static BlockId Generate(const Block& data); 26 | 27 | void writeTo(BlockingWriter& writer) const; 28 | 29 | bool operator==(const BlockId&) const; 30 | bool operator<(const BlockId&) const; 31 | 32 | std::size_t hash() const; 33 | 34 | std::string hexString() const; 35 | 36 | private: 37 | std::array data_; 38 | 39 | }; 40 | 41 | } 42 | 43 | } 44 | 45 | namespace std { 46 | 47 | template<> 48 | struct hash { 49 | std::size_t operator()(const p2p::FolderSync::BlockId& blockId) const { 50 | return blockId.hash(); 51 | } 52 | }; 53 | 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/BlockPath.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_BLOCKPATH_HPP 2 | #define P2P_FOLDERSYNC_BLOCKPATH_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace FolderSync { 14 | 15 | class BlockPath { 16 | public: 17 | static BlockPath Root(); 18 | 19 | static BlockPath Index(size_t blockIndex); 20 | 21 | bool isRoot() const; 22 | 23 | size_t size() const; 24 | 25 | size_t at(size_t index) const; 26 | 27 | size_t back() const; 28 | 29 | BlockPath parent() const; 30 | 31 | bool operator==(const BlockPath& path) const; 32 | 33 | std::size_t hash() const; 34 | 35 | private: 36 | BlockPath(); 37 | BlockPath(uint8_t pSize, const std::array& components); 38 | 39 | uint8_t size_; 40 | std::array components_; 41 | 42 | }; 43 | 44 | } 45 | 46 | } 47 | 48 | namespace std { 49 | 50 | template<> 51 | struct hash { 52 | std::size_t operator()(const p2p::FolderSync::BlockPath& path) const { 53 | return path.hash(); 54 | } 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/BlockReader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_BLOCKREADER_HPP 2 | #define P2P_FOLDERSYNC_BLOCKREADER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | namespace p2p { 16 | 17 | namespace FolderSync { 18 | 19 | class BlockReader: public BlockingReader { 20 | public: 21 | inline BlockReader(const Block& block, size_t position = 0) 22 | : block_(block), position_(position) { } 23 | 24 | inline void seek(size_t position) { 25 | position_ = position; 26 | } 27 | 28 | inline void readAll(uint8_t* data, size_t size) { 29 | if ((position_ + size) > BLOCK_SIZE) { 30 | throw std::runtime_error("Block read overflowed."); 31 | } 32 | memcpy(data, block_.data() + position_, size); 33 | position_ += size; 34 | } 35 | 36 | private: 37 | const Block& block_; 38 | size_t position_; 39 | 40 | }; 41 | 42 | } 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/BlockStore.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_BLOCKSTORE_HPP 2 | #define P2P_FOLDERSYNC_BLOCKSTORE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace p2p { 10 | 11 | namespace FolderSync { 12 | 13 | class BlockStore { 14 | public: 15 | virtual Block getRoot() const = 0; 16 | 17 | virtual void setRoot(Block block) = 0; 18 | 19 | virtual Block getBlock(const BlockPath& path, const Block& parentBlock) const = 0; 20 | 21 | virtual void setBlock(const BlockPath& path, Block& parentBlock, Block block) = 0; 22 | 23 | }; 24 | 25 | } 26 | 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/BlockWriter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_BLOCKWRITER_HPP 2 | #define P2P_FOLDERSYNC_BLOCKWRITER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | namespace p2p { 16 | 17 | namespace FolderSync { 18 | 19 | class BlockWriter: public BlockingWriter { 20 | public: 21 | inline BlockWriter(Block& block, size_t position = 0) 22 | : block_(block), position_(position) { } 23 | 24 | inline void seek(size_t position) { 25 | position_ = position; 26 | } 27 | 28 | inline void writeAll(const uint8_t* data, size_t size) { 29 | if ((position_ + size) > BLOCK_SIZE) { 30 | throw std::runtime_error("Block write overflowed."); 31 | } 32 | memcpy(block_.data() + position_, data, size); 33 | position_ += size; 34 | } 35 | 36 | private: 37 | Block& block_; 38 | size_t position_; 39 | 40 | }; 41 | 42 | } 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/Database.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_DATABASE_HPP 2 | #define P2P_FOLDERSYNC_DATABASE_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace FolderSync { 10 | 11 | class Database { 12 | public: 13 | virtual Block loadBlock(const BlockId& id) const = 0; 14 | 15 | virtual void storeBlock(const BlockId& id, Block data) = 0; 16 | 17 | }; 18 | 19 | } 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/Directory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_DIRECTORY_HPP 2 | #define P2P_FOLDERSYNC_DIRECTORY_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace FolderSync { 13 | 14 | class Directory { 15 | public: 16 | Directory(Node& node); 17 | ~Directory(); 18 | 19 | size_t childCount() const; 20 | 21 | void addChild(const std::string& name, const BlockId& blockId); 22 | 23 | void forceAddChild(const std::string& name, const BlockId& blockId); 24 | 25 | void updateChild(const std::string& name, const BlockId& blockId); 26 | 27 | void removeChild(const std::string& name); 28 | 29 | bool hasChild(const std::string& name) const; 30 | 31 | BlockId getChild(const std::string& name) const; 32 | 33 | std::vector childNames() const; 34 | 35 | private: 36 | Node& node_; 37 | 38 | }; 39 | 40 | } 41 | 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/FileDatabase.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_FILEDATABASE_HPP 2 | #define P2P_FOLDERSYNC_FILEDATABASE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace FolderSync { 13 | 14 | class FileDatabase: public Database { 15 | public: 16 | FileDatabase(const std::string& path); 17 | ~FileDatabase(); 18 | 19 | Block loadBlock(const BlockId& id) const; 20 | 21 | void storeBlock(const BlockId& id, Block data); 22 | 23 | private: 24 | // Non-copyable. 25 | FileDatabase(const FileDatabase&) = delete; 26 | FileDatabase& operator=(FileDatabase) = delete; 27 | 28 | std::unique_ptr impl_; 29 | 30 | }; 31 | 32 | } 33 | 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/Journal.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_JOURNAL_HPP 2 | #define P2P_FOLDERSYNC_JOURNAL_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace p2p { 9 | 10 | namespace FolderSync { 11 | 12 | class Journal { 13 | public: 14 | Journal(); 15 | 16 | void addNewRoot(const BlockId& blockId); 17 | 18 | const BlockId& rootId() const; 19 | 20 | private: 21 | std::vector entries_; 22 | 23 | }; 24 | 25 | } 26 | 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/MemDatabase.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_MEMDATABASE_HPP 2 | #define P2P_FOLDERSYNC_MEMDATABASE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace FolderSync { 13 | 14 | class MemDatabase: public Database { 15 | public: 16 | MemDatabase(); 17 | ~MemDatabase(); 18 | 19 | Block loadBlock(const BlockId& id) const; 20 | 21 | void storeBlock(const BlockId& id, Block data); 22 | 23 | private: 24 | std::unordered_map data_; 25 | 26 | }; 27 | 28 | } 29 | 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/Node.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_NODE_HPP 2 | #define P2P_FOLDERSYNC_NODE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace FolderSync { 13 | 14 | class Database; 15 | 16 | typedef uint64_t NodeSize; 17 | typedef uint64_t NodeOffset; 18 | 19 | enum NodeType { 20 | TYPE_DIRECTORY = 0, 21 | TYPE_FILE 22 | }; 23 | 24 | BlockId CreateEmptyNode(Database& database, NodeType type); 25 | 26 | class Node { 27 | public: 28 | Node(Database& database, const BlockId& initialBlockId); 29 | ~Node(); 30 | 31 | /** 32 | * \brief Get the node's block ID. 33 | * 34 | * If the node hasn't been modified (by a call 35 | * to 'write'), this will return the same ID as 36 | * passed in the constructor. 37 | */ 38 | BlockId blockId() const; 39 | 40 | /** 41 | * \brief Get node size (in bytes). 42 | */ 43 | NodeSize size() const; 44 | 45 | /** 46 | * \brief Get node type. 47 | */ 48 | NodeType type() const; 49 | 50 | /** 51 | * \brief Flush node changes. 52 | * 53 | * Writes the new node blocks to the database. 54 | * This will be called automatically when the 55 | * node is destroyed. 56 | */ 57 | void flush(); 58 | 59 | bool hasChanged() const; 60 | 61 | void resize(NodeSize size); 62 | 63 | size_t read(NodeOffset offset, uint8_t* buffer, size_t bufferSize) const; 64 | 65 | size_t write(NodeOffset offset, const uint8_t* buffer, size_t bufferSize); 66 | 67 | private: 68 | // Non-copyable. 69 | Node(const Node&) = delete; 70 | Node& operator=(Node) = delete; 71 | 72 | bool hasChanged_; 73 | NodeBlockStore blockStore_; 74 | BlockCache cache_; 75 | NodeSize size_; 76 | NodeType type_; 77 | 78 | }; 79 | 80 | } 81 | 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/NodeBlockStore.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_NODEBLOCKSTORE_HPP 2 | #define P2P_FOLDERSYNC_NODEBLOCKSTORE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace FolderSync { 14 | 15 | inline size_t NodeBlockIdOffset(const BlockPath& path) { 16 | const bool isDirectRef = path.size() == 1; 17 | return (isDirectRef ? NODE_BLOCK_ID_OFFSET : 0) + path.back() * BLOCK_ID_SIZE; 18 | } 19 | 20 | class NodeBlockStore: public BlockStore { 21 | public: 22 | NodeBlockStore(Database& database, const BlockId& rootId); 23 | ~NodeBlockStore(); 24 | 25 | const BlockId& rootId() const; 26 | 27 | Block getRoot() const; 28 | 29 | void setRoot(Block block); 30 | 31 | Block getBlock(const BlockPath& path, const Block& parentBlock) const; 32 | 33 | void setBlock(const BlockPath& path, Block& parentBlock, Block block); 34 | 35 | private: 36 | // Non-copyable. 37 | NodeBlockStore(const NodeBlockStore&) = delete; 38 | NodeBlockStore& operator=(NodeBlockStore) = delete; 39 | 40 | Database& database_; 41 | BlockId rootId_; 42 | 43 | }; 44 | 45 | } 46 | 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/NodeReader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_NODEREADER_HPP 2 | #define P2P_FOLDERSYNC_NODEREADER_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace FolderSync { 13 | 14 | class NodeReader: public BlockingReader { 15 | public: 16 | NodeReader(const Node& node, NodeOffset initialPosition = 0); 17 | 18 | NodeOffset position() const; 19 | 20 | void seek(NodeOffset newPosition); 21 | 22 | void readAll(uint8_t* data, size_t size); 23 | 24 | private: 25 | const Node& node_; 26 | NodeOffset position_; 27 | 28 | }; 29 | 30 | } 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/p2p/FolderSync/NodeWriter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_FOLDERSYNC_NODEWRITER_HPP 2 | #define P2P_FOLDERSYNC_NODEWRITER_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace FolderSync { 13 | 14 | class NodeWriter: public BlockingWriter { 15 | public: 16 | NodeWriter(Node& node, NodeOffset initialPosition = 0); 17 | 18 | NodeOffset position() const; 19 | 20 | void seek(NodeOffset newPosition); 21 | 22 | void writeAll(const uint8_t* data, size_t size); 23 | 24 | private: 25 | Node& node_; 26 | NodeOffset position_; 27 | 28 | }; 29 | 30 | } 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/p2p/IP.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_IP_HPP 2 | #define P2P_IP_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/p2p/IP/Address.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_IP_ADDRESS_HPP 2 | #define P2P_IP_ADDRESS_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace IP { 13 | 14 | typedef boost::asio::ip::address AddressImplType; 15 | 16 | struct Address { 17 | Version version; 18 | 19 | union { 20 | V4Address v4Address; 21 | V6Address v6Address; 22 | }; 23 | 24 | static AddressImplType ToImpl(const Address&); 25 | 26 | static Address FromImpl(const AddressImplType&); 27 | 28 | Address(); 29 | Address(const V4Address& pAddress); 30 | Address(const V6Address& pAddress); 31 | 32 | bool operator==(const Address& other) const; 33 | bool operator!=(const Address& other) const; 34 | bool operator<(const Address& other) const; 35 | 36 | std::string toString() const; 37 | 38 | }; 39 | 40 | } 41 | 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/p2p/IP/V4Address.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_IP_V4ADDRESS_HPP 2 | #define P2P_IP_V4ADDRESS_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace IP { 14 | 15 | typedef boost::asio::ip::address_v4 V4AddressImplType; 16 | 17 | struct V4Address { 18 | std::array data; 19 | 20 | static V4AddressImplType ToImpl(const V4Address&); 21 | 22 | static V4Address FromImpl(const V4AddressImplType&); 23 | 24 | static V4Address Any(); 25 | 26 | static V4Address Broadcast(); 27 | 28 | static V4Address Localhost(); 29 | 30 | static V4Address Netmask(const V4Address&); 31 | 32 | bool operator==(const V4Address& other) const; 33 | bool operator<(const V4Address& other) const; 34 | 35 | std::string toString() const; 36 | 37 | }; 38 | 39 | } 40 | 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/p2p/IP/V6Address.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_IP_V6ADDRESS_HPP 2 | #define P2P_IP_V6ADDRESS_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace IP { 14 | 15 | typedef boost::asio::ip::address_v6 V6AddressImplType; 16 | 17 | struct V6Address { 18 | std::array data; 19 | 20 | static V6AddressImplType ToImpl(const V6Address&); 21 | 22 | static V6Address FromImpl(const V6AddressImplType&); 23 | 24 | static V6Address Any(); 25 | 26 | static V6Address Localhost(); 27 | 28 | bool operator==(const V6Address& other) const; 29 | bool operator<(const V6Address& other) const; 30 | 31 | std::string toString() const; 32 | 33 | }; 34 | 35 | } 36 | 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/p2p/IP/Version.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_IP_VERSION_HPP 2 | #define P2P_IP_VERSION_HPP 3 | 4 | namespace p2p { 5 | 6 | namespace IP { 7 | 8 | enum Version { 9 | v4, 10 | v6 11 | }; 12 | 13 | } 14 | 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/p2p/Kademlia.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_KADEMLIA_HPP 2 | #define P2P_KADEMLIA_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/p2p/Kademlia/SearchQueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_KADEMLIA_SEARCHQUEUE_HPP 2 | #define P2P_KADEMLIA_SEARCHQUEUE_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace Kademlia { 10 | 11 | template 12 | class SearchQueue { 13 | struct Compare { 14 | const IdType& id_; 15 | 16 | Compare(const IdType& id) : id_(id) { } 17 | 18 | bool operator()(const IdType& a, const IdType& b) const { 19 | const auto& aDiff = a ^ id_; 20 | const auto& bDiff = b ^ id_; 21 | 22 | if (aDiff == bDiff) { 23 | return a < b; 24 | } else { 25 | return aDiff < bDiff; 26 | } 27 | } 28 | }; 29 | 30 | public: 31 | SearchQueue(const IdType& targetId) : targetId_(targetId), map_(Compare(targetId_)) { } 32 | 33 | IdType distance() const { 34 | return map_.empty() ? IdType::Max() : map_.begin()->first ^ targetId_; 35 | } 36 | 37 | size_t size() const { 38 | return map_.size(); 39 | } 40 | 41 | void add(const IdType& id) { 42 | map_.insert(std::make_pair(id, false)); 43 | } 44 | 45 | bool isNearestVisited() const { 46 | return map_.empty() ? true : (map_.begin())->second; 47 | } 48 | 49 | void setVisited(const IdType& id) { 50 | map_.at(id) = true; 51 | } 52 | 53 | std::vector getNearest(size_t maxSize) const { 54 | std::vector group; 55 | 56 | for (const auto& idPair: map_) { 57 | if (group.size() == maxSize) break; 58 | group.push_back(idPair.first); 59 | } 60 | 61 | return group; 62 | } 63 | 64 | std::vector getNearestUnvisited(size_t maxSize) const { 65 | std::vector group; 66 | 67 | for (const auto& idPair: map_) { 68 | if (group.size() == maxSize) break; 69 | 70 | if (!idPair.second) { 71 | group.push_back(idPair.first); 72 | } 73 | } 74 | 75 | return group; 76 | } 77 | 78 | private: 79 | IdType targetId_; 80 | std::map map_; 81 | 82 | }; 83 | 84 | } 85 | 86 | } 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /include/p2p/OFTorrent.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | -------------------------------------------------------------------------------- /include/p2p/OFTorrent/BlockStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_OFTORRENT_BLOCKSTREAM_HPP 2 | #define P2P_OFTORRENT_BLOCKSTREAM_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace OFTorrent { 10 | 11 | enum BlockSize { 12 | BLOCKSIZE_512KB = 512 * 1024 13 | }; 14 | 15 | class BlockStream: public OStream { 16 | public: 17 | BlockStream(OutputStreamGenerator&, BlockSize); 18 | 19 | bool isValid() const; 20 | 21 | Event::Source eventSource() const; 22 | 23 | size_t write(const uint8_t* data, size_t dataSize); 24 | 25 | private: 26 | OutputStreamGenerator& generator_; 27 | OStream* stream_; 28 | size_t blockPos_, blockSize_; 29 | 30 | }; 31 | 32 | } 33 | 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/p2p/OFTorrent/StreamGenerator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_OFTORRENT_STREAMGENERATOR_HPP 2 | #define P2P_OFTORRENT_STREAMGENERATOR_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace OFTorrent { 9 | 10 | class OutputStreamGenerator { 11 | public: 12 | virtual OStream& getNextOutputStream() = 0; 13 | 14 | }; 15 | 16 | } 17 | 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/p2p/OFTorrent/XORStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_OFTORRENT_XORSTREAM_HPP 2 | #define P2P_OFTORRENT_XORSTREAM_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace OFTorrent { 13 | 14 | /** 15 | * A stream that reads from two streams, and xors them together. 16 | */ 17 | class XORStream: public IStream { 18 | public: 19 | XORStream(IStream& source0, IStream& source1); 20 | 21 | bool isValid() const; 22 | 23 | Event::Source eventSource() const; 24 | 25 | size_t read(uint8_t* data, size_t size); 26 | 27 | private: 28 | BufferedStream source0_; 29 | BufferedStream source1_; 30 | 31 | }; 32 | 33 | } 34 | 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/p2p/RPC.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_RPC_HPP 2 | #define P2P_RPC_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/p2p/RPC/ChainedOperationData.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_RPC_CHAINEDOPERATIONDATA_HPP 2 | #define P2P_RPC_CHAINEDOPERATIONDATA_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace RPC { 14 | 15 | template 16 | class ChainedOperationData: public RetrieveAPI { 17 | public: 18 | ChainedOperationData(std::unique_ptr>&& originalSource, Operator function) 19 | : originalSource_(std::move(originalSource)), 20 | function_(std::move(function)) { } 21 | 22 | Event::Source eventSource() const { 23 | return originalSource_->eventSource(); 24 | } 25 | 26 | bool isComplete() const { 27 | return originalSource_->isComplete(); 28 | } 29 | 30 | ResultType get() { 31 | return function_(originalSource_->get()); 32 | } 33 | 34 | private: 35 | std::unique_ptr> originalSource_; 36 | Operator function_; 37 | 38 | }; 39 | 40 | } 41 | 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/p2p/RPC/Host.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_RPC_HOST_HPP 2 | #define P2P_RPC_HOST_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace RPC { 17 | 18 | template 19 | class Host: public HostAPI { 20 | public: 21 | using DataType = OperationData; 22 | 23 | Host() { } 24 | ~Host() { } 25 | 26 | Operation startOperation(const TokenType& token) { 27 | auto operationData = std::unique_ptr(new DataType(*this, token)); 28 | return Operation(std::move(operationData)); 29 | } 30 | 31 | void completeOperation(const TokenType& token, ResultType result) { 32 | std::lock_guard lock(mutex_); 33 | const auto iterator = dataMap_.find(token); 34 | if (iterator == dataMap_.end()) return; 35 | iterator->second->operationComplete(std::move(result)); 36 | dataMap_.erase(iterator); 37 | } 38 | 39 | private: 40 | void add(const TokenType& token, PushAPI* pushData) { 41 | std::lock_guard lock(mutex_); 42 | dataMap_.emplace(token, pushData); 43 | } 44 | 45 | void remove(const TokenType& token) { 46 | std::lock_guard lock(mutex_); 47 | dataMap_.erase(token); 48 | } 49 | 50 | std::mutex mutex_; 51 | std::unordered_map*> dataMap_; 52 | 53 | }; 54 | 55 | } 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/p2p/RPC/HostAPI.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_RPC_HOSTAPI_HPP 2 | #define P2P_RPC_HOSTAPI_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace RPC { 9 | 10 | template 11 | class HostAPI { 12 | public: 13 | inline virtual ~HostAPI() { } 14 | 15 | virtual void add(const TokenType& token, PushAPI* pushData) = 0; 16 | 17 | virtual void remove(const TokenType& token) = 0; 18 | 19 | }; 20 | 21 | } 22 | 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/p2p/RPC/IdGenerator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_RPC_IDGENERATOR_HPP 2 | #define P2P_RPC_IDGENERATOR_HPP 3 | 4 | namespace p2p { 5 | 6 | namespace RPC { 7 | 8 | template 9 | class IdGenerator { 10 | public: 11 | virtual IdType generate() = 0; 12 | 13 | }; 14 | 15 | } 16 | 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/p2p/RPC/Operation.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_RPC_OPERATION_HPP 2 | #define P2P_RPC_OPERATION_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace RPC { 16 | 17 | template 18 | class Operation { 19 | public: 20 | Operation(std::unique_ptr>&& data) 21 | : data_(std::move(data)) { } 22 | 23 | Event::Source eventSource() const { 24 | return data_->eventSource(); 25 | } 26 | 27 | bool isComplete() const { 28 | return data_->isComplete(); 29 | } 30 | 31 | ResultType get() { 32 | wait(); 33 | return data_->get(); 34 | } 35 | 36 | void wait() const { 37 | while (!isComplete()) { 38 | Event::Wait({ eventSource() }); 39 | } 40 | } 41 | 42 | std::unique_ptr> detach() { 43 | return std::move(data_); 44 | } 45 | 46 | private: 47 | std::unique_ptr> data_; 48 | 49 | }; 50 | 51 | template 52 | auto Chain(Operation operation, Operator function) -> Operation { 53 | using ResultType = decltype(function(operation.get())); 54 | auto newSource = std::unique_ptr>( 55 | new ChainedOperationData(std::move(operation.detach()), std::move(function))); 56 | return Operation(std::move(newSource)); 57 | } 58 | 59 | } 60 | 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /include/p2p/RPC/OperationData.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_RPC_OPERATIONDATA_HPP 2 | #define P2P_RPC_OPERATIONDATA_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace p2p { 17 | 18 | namespace RPC { 19 | 20 | template 21 | class OperationData: public PushAPI, public RetrieveAPI { 22 | public: 23 | OperationData(HostAPI& host, TokenType token) 24 | : host_(host), result_(boost::none), token_(token) { 25 | host_.add(token_, this); 26 | } 27 | 28 | ~OperationData() { 29 | host_.remove(token_); 30 | } 31 | 32 | void operationComplete(ResultType&& result) { 33 | std::lock_guard lock(mutex_); 34 | result_ = boost::optional(std::move(result)); 35 | generator_.activate(); 36 | } 37 | 38 | Event::Source eventSource() const { 39 | return generator_.eventSource(); 40 | } 41 | 42 | bool isComplete() const { 43 | std::lock_guard lock(mutex_); 44 | return result_; 45 | } 46 | 47 | ResultType get() { 48 | std::lock_guard lock(mutex_); 49 | if (!result_) { 50 | throw std::runtime_error("Result not available."); 51 | } 52 | ResultType result = std::move(*result_); 53 | result_ = boost::none; 54 | return result; 55 | } 56 | 57 | private: 58 | mutable std::mutex mutex_; 59 | Event::Generator generator_; 60 | HostAPI& host_; 61 | boost::optional result_; 62 | TokenType token_; 63 | 64 | }; 65 | 66 | } 67 | 68 | } 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /include/p2p/RPC/PushAPI.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_RPC_PUSHAPI_HPP 2 | #define P2P_RPC_PUSHAPI_HPP 3 | 4 | namespace p2p { 5 | 6 | namespace RPC { 7 | 8 | template 9 | class PushAPI { 10 | public: 11 | inline virtual ~PushAPI() { } 12 | 13 | virtual void operationComplete(ResultType&& result) = 0; 14 | 15 | }; 16 | 17 | } 18 | 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /include/p2p/RPC/RetrieveAPI.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_RPC_RETRIEVEAPI_HPP 2 | #define P2P_RPC_RETRIEVEAPI_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace RPC { 9 | 10 | template 11 | class RetrieveAPI { 12 | public: 13 | inline virtual ~RetrieveAPI() { } 14 | 15 | virtual Event::Source eventSource() const = 0; 16 | 17 | virtual bool isComplete() const = 0; 18 | 19 | virtual ResultType get() = 0; 20 | 21 | }; 22 | 23 | } 24 | 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /include/p2p/Root.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_HPP 2 | #define P2P_ROOTNETWORK_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/p2p/Root/AuthenticatedSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_AUTHENTICATEDSOCKET_HPP 2 | #define P2P_ROOTNETWORK_AUTHENTICATEDSOCKET_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace p2p { 17 | 18 | namespace Root { 19 | 20 | class PrivateIdentity; 21 | 22 | class IdentityDelegate { 23 | public: 24 | virtual PrivateIdentity& getPrivateIdentity() = 0; 25 | 26 | virtual PublicIdentity& getPublicIdentity(const PublicKey& publicKey) = 0; 27 | 28 | }; 29 | 30 | class AuthenticatedSocket: public Socket { 31 | public: 32 | AuthenticatedSocket(IdentityDelegate& delegate, Socket& socket); 33 | 34 | bool isValid() const; 35 | 36 | Event::Source eventSource() const; 37 | 38 | bool receive(NodePair& nodePair, Message& message); 39 | 40 | bool send(const NodePair& nodePair, const Message& message); 41 | 42 | private: 43 | // Non-blocking. 44 | AuthenticatedSocket(const AuthenticatedSocket&) = delete; 45 | AuthenticatedSocket& operator=(AuthenticatedSocket) = delete; 46 | 47 | IdentityDelegate& delegate_; 48 | Socket& socket_; 49 | 50 | }; 51 | 52 | } 53 | 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/p2p/Root/ClientHost.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_CLIENTHOST_HPP 2 | #define P2P_ROOTNETWORK_CLIENTHOST_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace Root { 17 | 18 | class ClientHostDelegate: public IdentityDelegate, public NodeDetectDelegate { 19 | public: 20 | virtual Socket& getUDPSocket() = 0; 21 | 22 | }; 23 | 24 | class ClientHost { 25 | public: 26 | ClientHost(ClientHostDelegate& delegate); 27 | ~ClientHost(); 28 | 29 | RoutineIdGenerator& idGenerator(); 30 | 31 | MultiplexHost& socketHost(); 32 | 33 | 34 | 35 | }; 36 | 37 | } 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/p2p/Root/Core/RPCClient.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_CORE_RPCCLIENT_HPP 2 | #define P2P_ROOTNETWORK_CORE_RPCCLIENT_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | 19 | namespace p2p { 20 | 21 | namespace Root { 22 | 23 | namespace Core { 24 | 25 | class RPCClient { 26 | public: 27 | RPCClient(Socket& socket, RoutineIdGenerator& routineIdGenerator, double timeoutMilliseconds = 500.0); 28 | ~RPCClient(); 29 | 30 | Event::Source eventSource() const; 31 | 32 | bool processResponse(); 33 | 34 | RPC::Operation identify(const Endpoint& endpoint); 35 | 36 | RPC::Operation ping(const Endpoint& endpoint, const NodeId& nodeId); 37 | 38 | RPC::Operation> queryNetworks(const Endpoint& endpoint, const NodeId& nodeId); 39 | 40 | private: 41 | // Non-copyable. 42 | RPCClient(const RPCClient&) = delete; 43 | RPCClient& operator=(RPCClient) = delete; 44 | 45 | Socket& socket_; 46 | MessageResender resender_; 47 | Event::UnionGenerator unionGenerator_; 48 | RoutineIdGenerator& routineIdGenerator_; 49 | RPC::Host identifyHost_; 50 | RPC::Host pingHost_; 51 | RPC::Host, RoutineId> queryNetworksHost_; 52 | 53 | }; 54 | 55 | } 56 | 57 | } 58 | 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /include/p2p/Root/Core/RPCMessage.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_CORE_RPCMESSAGE_HPP 2 | #define P2P_ROOTNETWORK_CORE_RPCMESSAGE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace Root { 14 | 15 | namespace Core { 16 | 17 | class RPCMessage { 18 | public: 19 | static RPCMessage IdentifyRequest(); 20 | static RPCMessage IdentifyReply(const Endpoint& endpoint); 21 | 22 | static RPCMessage PingRequest(); 23 | static RPCMessage PingReply(const Endpoint& endpoint); 24 | 25 | static RPCMessage QueryNetworksRequest(); 26 | static RPCMessage QueryNetworksReply(const std::vector& networks); 27 | 28 | // TODO 29 | // static RPCMessage KeyExchangeRequest(); 30 | // static RPCMessage KeyExchangeRequest(); 31 | 32 | enum Kind { 33 | IDENTIFY = 0, 34 | PING = 1, 35 | QUERY_NETWORKS = 4, 36 | KEY_EXCHANGE = 8 37 | }; 38 | 39 | Kind kind() const; 40 | State state() const; 41 | const Endpoint& endpoint() const; 42 | const std::vector& networks() const; 43 | 44 | Buffer toPayload() const; 45 | 46 | Message createMessage(uint32_t routine) const; 47 | 48 | private: 49 | RPCMessage(Kind kind, State state); 50 | 51 | Kind kind_; 52 | State state_; 53 | Endpoint endpoint_; 54 | std::vector networks_; 55 | 56 | 57 | }; 58 | 59 | } 60 | 61 | } 62 | 63 | } 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /include/p2p/Root/Core/RPCServer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_CORE_RPCSERVER_HPP 2 | #define P2P_ROOTNETWORK_CORE_RPCSERVER_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace p2p { 16 | 17 | namespace Root { 18 | 19 | namespace Core { 20 | 21 | class RPCServer { 22 | public: 23 | RPCServer(Socket& socket); 24 | ~RPCServer(); 25 | 26 | Event::Source eventSource() const; 27 | 28 | void addNetwork(const std::string& networkName); 29 | 30 | bool processRequest(); 31 | 32 | private: 33 | // Non-copyable. 34 | RPCServer(const RPCServer&) = delete; 35 | RPCServer& operator=(RPCServer) = delete; 36 | 37 | Socket& socket_; 38 | std::vector networks_; 39 | 40 | }; 41 | 42 | } 43 | 44 | } 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/p2p/Root/Core/Service.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_CORE_SERVICE_HPP 2 | #define P2P_ROOTNETWORK_CORE_SERVICE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | namespace p2p { 23 | 24 | namespace Root { 25 | 26 | namespace Core { 27 | 28 | class Service { 29 | public: 30 | Service(Socket& socket, RoutineIdGenerator& routineIdGenerator); 31 | ~Service(); 32 | 33 | Event::Source eventSource() const; 34 | 35 | bool processMessage(); 36 | 37 | void addNetwork(const std::string& networkName); 38 | 39 | RPC::Operation identify(const Endpoint& endpoint); 40 | 41 | RPC::Operation ping(const Endpoint& endpoint, const NodeId& nodeId); 42 | 43 | RPC::Operation> queryNetworks(const Endpoint& endpoint, const NodeId& nodeId); 44 | 45 | private: 46 | // Non-copyable. 47 | Service(const Service&) = delete; 48 | Service& operator=(Service) = delete; 49 | 50 | Socket& socket_; 51 | MultiplexHost multiplexHost_; 52 | MultiplexClient clientSocket_; 53 | MultiplexClient serverSocket_; 54 | RPCClient client_; 55 | RPCServer server_; 56 | Event::UnionGenerator unionGenerator_; 57 | 58 | }; 59 | 60 | } 61 | 62 | } 63 | 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /include/p2p/Root/DHT/RPCClient.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_DHT_RPCCLIENT_HPP 2 | #define P2P_ROOTNETWORK_DHT_RPCCLIENT_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | namespace p2p { 23 | 24 | namespace Root { 25 | 26 | namespace DHT { 27 | 28 | struct Empty {}; 29 | 30 | class RPCClient { 31 | public: 32 | RPCClient(Socket& socket, RoutineIdGenerator& routineIdGenerator, double timeoutMilliseconds = 500.0); 33 | ~RPCClient(); 34 | 35 | Event::Source eventSource() const; 36 | 37 | bool processResponse(); 38 | 39 | RPC::Operation> getNearestNodes(const NodeId& destId, const NodeId& targetId); 40 | 41 | RPC::Operation subscribe(const NodeId& destId, const NodeId& targetId, const std::vector& myEndpoints); 42 | 43 | RPC::Operation> getSubscribers(const NodeId& destId, const NodeId& targetId); 44 | 45 | private: 46 | // Non-copyable. 47 | RPCClient(const RPCClient&) = delete; 48 | RPCClient& operator=(RPCClient) = delete; 49 | 50 | Socket& socket_; 51 | MessageResender resender_; 52 | Event::UnionGenerator unionGenerator_; 53 | RoutineIdGenerator& routineIdGenerator_; 54 | RPC::Host, RoutineId> getNearestHost_; 55 | RPC::Host subscribeHost_; 56 | RPC::Host, RoutineId> getSubscribersHost_; 57 | 58 | }; 59 | 60 | } 61 | 62 | } 63 | 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /include/p2p/Root/DHT/RPCFindSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_DHT_RPCFINDSOCKET_HPP 2 | #define P2P_ROOTNETWORK_DHT_RPCFINDSOCKET_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace p2p { 13 | 14 | namespace Root { 15 | 16 | namespace DHT { 17 | 18 | class RPCFindSocket: public Kademlia::RPCSocket { 19 | public: 20 | RPCFindSocket(Socket& socket, RoutineIdGenerator& routineIdGenerator); 21 | ~RPCFindSocket(); 22 | 23 | Event::Source eventSource() const; 24 | 25 | RPC::Operation> performFind(const NodeId& destId, const NodeId& searchId); 26 | 27 | private: 28 | // Non-copyable. 29 | RPCFindSocket(const RPCFindSocket&) = delete; 30 | RPCFindSocket& operator=(RPCFindSocket) = delete; 31 | 32 | Socket& socket_; 33 | RoutineIdGenerator& routineIdGenerator_; 34 | 35 | }; 36 | 37 | } 38 | 39 | } 40 | 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/p2p/Root/DHT/RPCMessage.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_DHT_RPCMESSAGE_HPP 2 | #define P2P_ROOTNETWORK_DHT_RPCMESSAGE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace Root { 16 | 17 | namespace DHT { 18 | 19 | class RPCMessage { 20 | public: 21 | static RPCMessage GetNearestNodesRequest(const NodeId& targetId); 22 | static RPCMessage GetNearestNodesReply(const std::vector& nodeList); 23 | 24 | static RPCMessage SubscribeRequest(const NodeId& targetId, const std::vector& myEndpoints); 25 | static RPCMessage SubscribeReply(); 26 | 27 | static RPCMessage GetSubscribersRequest(const NodeId& targetId); 28 | static RPCMessage GetSubscribersReply(const std::vector& nodeList); 29 | 30 | enum Kind { 31 | GET_NEAREST_NODES = 0, 32 | SUBSCRIBE = 8, 33 | GET_SUBSCRIBERS = 9 34 | }; 35 | 36 | Kind kind() const; 37 | State state() const; 38 | const NodeId& targetId() const; 39 | const std::vector& endpointList() const; 40 | const std::vector& nodeList() const; 41 | 42 | Buffer toPayload() const; 43 | 44 | Message createMessage(RoutineId routine) const; 45 | 46 | private: 47 | RPCMessage(Kind kind, State state); 48 | 49 | Kind kind_; 50 | State state_; 51 | NodeId targetId_; 52 | std::vector myEndpoints_; 53 | std::vector nodeList_; 54 | 55 | 56 | }; 57 | 58 | } 59 | 60 | } 61 | 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/p2p/Root/DHT/RPCServer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_DHT_RPCSERVER_HPP 2 | #define P2P_ROOTNETWORK_DHT_RPCSERVER_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace Root { 16 | 17 | namespace DHT { 18 | 19 | class RPCServer { 20 | public: 21 | RPCServer(Socket& socket, ServerDelegate& delegate); 22 | ~RPCServer(); 23 | 24 | Event::Source eventSource() const; 25 | 26 | bool processRequest(); 27 | 28 | private: 29 | // Non-copyable. 30 | RPCServer(const RPCServer&) = delete; 31 | RPCServer& operator=(RPCServer) = delete; 32 | 33 | Socket& socket_; 34 | ServerDelegate& delegate_; 35 | 36 | }; 37 | 38 | } 39 | 40 | } 41 | 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/p2p/Root/DHT/ServerDelegate.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_DHT_SERVERDELEGATE_HPP 2 | #define P2P_ROOTNETWORK_DHT_SERVERDELEGATE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace p2p { 10 | 11 | namespace Root { 12 | 13 | namespace DHT { 14 | 15 | class ServerDelegate { 16 | public: 17 | virtual std::vector getNearestNodes(const NodeId& targetId) = 0; 18 | 19 | virtual void subscribe(const NodeId& targetId, const NodeInfo& nodeInfo) = 0; 20 | 21 | virtual std::vector getSubscribers(const NodeId& targetId) = 0; 22 | 23 | }; 24 | 25 | } 26 | 27 | } 28 | 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/p2p/Root/DHT/Service.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_DHT_SERVICE_HPP 2 | #define P2P_ROOTNETWORK_DHT_SERVICE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | namespace p2p { 23 | 24 | namespace Root { 25 | 26 | namespace DHT { 27 | 28 | class Service { 29 | public: 30 | Service(Socket& socket, RoutineIdGenerator& routineIdGenerator, ServerDelegate& delegate); 31 | ~Service(); 32 | 33 | Event::Source eventSource() const; 34 | 35 | bool processMessage(); 36 | 37 | RPC::Operation> getNearestNodes(const NodeId& destId, const NodeId& targetId); 38 | 39 | RPC::Operation subscribe(const NodeId& destId, const NodeId& targetId, const std::vector& myEndpoints); 40 | 41 | RPC::Operation> getSubscribers(const NodeId& destId, const NodeId& targetId); 42 | 43 | private: 44 | // Non-copyable. 45 | Service(const Service&) = delete; 46 | Service& operator=(Service) = delete; 47 | 48 | Socket& socket_; 49 | MultiplexHost multiplexHost_; 50 | MultiplexClient clientSocket_; 51 | MultiplexClient serverSocket_; 52 | RPCClient client_; 53 | RPCServer server_; 54 | Event::UnionGenerator unionGenerator_; 55 | 56 | }; 57 | 58 | } 59 | 60 | } 61 | 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/p2p/Root/Endpoint.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_ENDPOINT_HPP 2 | #define P2P_ROOTNETWORK_ENDPOINT_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace p2p { 10 | 11 | namespace Root { 12 | 13 | struct Endpoint { 14 | enum Kind { 15 | LOCAL = 0, 16 | UDPIPV4 = 1, 17 | UDPIPV6 = 2, 18 | TCPIPV4 = 3, 19 | TCPIPV6 = 4 20 | } kind; 21 | 22 | UDP::Endpoint udpEndpoint; 23 | TCP::Endpoint tcpEndpoint; 24 | 25 | Endpoint(); 26 | Endpoint(const UDP::Endpoint& udpEndpoint); 27 | 28 | static Endpoint Read(BlockingReader& reader); 29 | 30 | bool operator<(const Endpoint& endpoint) const; 31 | 32 | void writeTo(BlockingWriter& writer) const; 33 | 34 | std::string toString() const; 35 | }; 36 | 37 | } 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/p2p/Root/EndpointMapSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_ENDPOINTMAPSOCKET_HPP 2 | #define P2P_ROOTNETWORK_ENDPOINTMAPSOCKET_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace Root { 17 | 18 | class EndpointMapSocket: public Socket { 19 | public: 20 | EndpointMapSocket(Socket& socket, NodeDatabase& database); 21 | 22 | bool isValid() const; 23 | 24 | Event::Source eventSource() const; 25 | 26 | bool receive(NodeId& nodeId, Message& message); 27 | 28 | bool send(const NodeId& nodeId, const Message& message); 29 | 30 | private: 31 | EndpointMapSocket(const EndpointMapSocket&) = delete; 32 | EndpointMapSocket& operator=(EndpointMapSocket) = delete; 33 | 34 | Socket& socket_; 35 | NodeDatabase& database_; 36 | 37 | }; 38 | 39 | } 40 | 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/p2p/Root/Key.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_KEY_HPP 2 | #define P2P_ROOTNETWORK_KEY_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace Root { 10 | 11 | using PrivateKey = Crypt::ECDSA::PrivateKey; 12 | using PublicKey = Crypt::ECDSA::PublicKey; 13 | 14 | } 15 | 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/p2p/Root/Message.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_MESSAGE_HPP 2 | #define P2P_ROOTNETWORK_MESSAGE_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace Root { 17 | 18 | /** 19 | * \brief Message 20 | * 21 | * Higher level representation of messages 22 | * sent between nodes. 23 | */ 24 | struct Message { 25 | boost::optional subnetwork; 26 | uint8_t type; 27 | 28 | uint32_t routine; 29 | State routineState; 30 | 31 | Buffer payload; 32 | 33 | inline Message() 34 | : subnetwork(boost::none), 35 | type(0), 36 | routine(0), 37 | routineState(STATE_0) { } 38 | }; 39 | 40 | } 41 | 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/p2p/Root/MessageResender.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_MESSAGERESENDER_HPP 2 | #define P2P_ROOTNETWORK_MESSAGERESENDER_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace Root { 17 | 18 | template 19 | class MessageResender { 20 | public: 21 | MessageResender(Socket& socket, double timeoutMilliseconds) 22 | : socket_(socket) { 23 | timer_.setMilliseconds(timeoutMilliseconds); 24 | timer_.schedule(); 25 | } 26 | 27 | Event::Source eventSource() const { 28 | return timer_.eventSource(); 29 | } 30 | 31 | void processResends() { 32 | if (!timer_.hasExpired()) return; 33 | 34 | // Re-send requests. 35 | for (const auto& messagePair: routineMap_) { 36 | const auto& routineMessage = messagePair.second; 37 | socket_.send(routineMessage.endpoint, routineMessage.message); 38 | } 39 | 40 | timer_.schedule(); 41 | } 42 | 43 | void startRoutine(RoutineId id, const EndpointType& endpoint, const Message& message) { 44 | routineMap_.insert(std::make_pair(id, RoutineMessage(endpoint, message))); 45 | (void) socket_.send(endpoint, message); 46 | } 47 | 48 | void endRoutine(RoutineId id) { 49 | routineMap_.erase(id); 50 | } 51 | 52 | private: 53 | // Non-copyable. 54 | MessageResender(const MessageResender&) = delete; 55 | MessageResender& operator=(MessageResender) = delete; 56 | 57 | struct RoutineMessage { 58 | EndpointType endpoint; 59 | Message message; 60 | 61 | inline RoutineMessage(EndpointType pEndpoint, Message pMessage) 62 | : endpoint(std::move(pEndpoint)), 63 | message(std::move(pMessage)) { } 64 | }; 65 | 66 | Event::Timer timer_; 67 | std::map routineMap_; 68 | Socket& socket_; 69 | 70 | }; 71 | 72 | } 73 | 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /include/p2p/Root/NetworkId.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_NETWORKID_HPP 2 | #define P2P_ROOTNETWORK_NETWORKID_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace Root { 17 | 18 | class NetworkId { 19 | public: 20 | NetworkId(); 21 | 22 | static NetworkId Zero(); 23 | static NetworkId FromReader(BlockingReader& reader); 24 | 25 | static NetworkId Generate(const std::string& networkName); 26 | 27 | void writeTo(BlockingWriter& writer) const; 28 | 29 | bool operator==(const NetworkId&) const; 30 | bool operator!=(const NetworkId&) const; 31 | bool operator<(const NetworkId&) const; 32 | 33 | std::size_t hash() const; 34 | 35 | std::string hexString() const; 36 | 37 | private: 38 | std::array data_; 39 | 40 | }; 41 | 42 | } 43 | 44 | } 45 | 46 | namespace std { 47 | 48 | template<> 49 | struct hash { 50 | std::size_t operator()(const p2p::Root::NetworkId& id) const { 51 | return id.hash(); 52 | } 53 | }; 54 | 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /include/p2p/Root/NodeDatabase.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_NODEDATABASE_HPP 2 | #define P2P_ROOTNETWORK_NODEDATABASE_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace Root { 17 | 18 | struct NodeEntry { 19 | PublicIdentity identity; 20 | std::set endpointSet; 21 | 22 | inline NodeEntry(PublicIdentity pIdentity) 23 | : identity(std::move(pIdentity)) { } 24 | 25 | inline NodeId id() const { 26 | return identity.id(); 27 | } 28 | 29 | inline NodeInfo toNodeInfo() const { 30 | return NodeInfo(id(), endpointSet); 31 | } 32 | }; 33 | 34 | class NodeDatabase { 35 | public: 36 | NodeDatabase(); 37 | 38 | bool isKnownId(const NodeId& id) const; 39 | 40 | void addNode(const NodeId& id, NodeEntry nodeInfo); 41 | 42 | NodeEntry& nodeEntry(const NodeId& id); 43 | 44 | const NodeEntry& nodeEntry(const NodeId& id) const; 45 | 46 | inline const std::unordered_map& map() const { 47 | return map_; 48 | } 49 | 50 | private: 51 | // Non-copyable. 52 | NodeDatabase(const NodeDatabase&) = delete; 53 | NodeDatabase& operator=(const NodeDatabase&) = delete; 54 | 55 | std::unordered_map map_; 56 | 57 | }; 58 | 59 | } 60 | 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /include/p2p/Root/NodeDetectSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_NODEDETECTSOCKET_HPP 2 | #define P2P_ROOTNETWORK_NODEDETECTSOCKET_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace Root { 14 | 15 | class NodeDetectDelegate { 16 | public: 17 | virtual void detectedNodePair(const NodePair& nodePair) = 0; 18 | 19 | }; 20 | 21 | class NodeDetectSocket: public Socket { 22 | public: 23 | NodeDetectSocket(Socket& socket, NodeDetectDelegate& delegate); 24 | 25 | bool isValid() const; 26 | 27 | Event::Source eventSource() const; 28 | 29 | bool receive(NodePair& nodePair, Message& message); 30 | 31 | bool send(const NodePair& nodePair, const Message& message); 32 | 33 | private: 34 | NodeDetectSocket(const NodeDetectSocket&) = delete; 35 | NodeDetectSocket& operator=(NodeDetectSocket) = delete; 36 | 37 | Socket& socket_; 38 | NodeDetectDelegate& delegate_; 39 | 40 | }; 41 | 42 | } 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/p2p/Root/NodeId.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_NODEID_HPP 2 | #define P2P_ROOTNETWORK_NODEID_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace Root { 17 | 18 | class NodeId { 19 | public: 20 | static constexpr size_t SIZE_IN_BITS = NODE_ID_SIZE_BITS; 21 | 22 | NodeId(); 23 | 24 | static NodeId Zero(); 25 | static NodeId Max(); 26 | 27 | static NodeId FromReader(BlockingReader& reader); 28 | 29 | static NodeId Generate(const PublicKey& publicKey); 30 | 31 | void writeTo(BlockingWriter& writer) const; 32 | 33 | bool bitAt(size_t index) const; 34 | 35 | uint8_t operator[](size_t index) const; 36 | uint8_t& operator[](size_t index); 37 | 38 | bool operator==(const NodeId&) const; 39 | bool operator!=(const NodeId&) const; 40 | bool operator<(const NodeId&) const; 41 | 42 | NodeId operator^(const NodeId&) const; 43 | NodeId operator~() const; 44 | 45 | std::size_t hash() const; 46 | 47 | std::string hexString() const; 48 | 49 | private: 50 | std::array data_; 51 | 52 | }; 53 | 54 | } 55 | 56 | } 57 | 58 | namespace std { 59 | 60 | template<> 61 | struct hash { 62 | std::size_t operator()(const p2p::Root::NodeId& id) const { 63 | return id.hash(); 64 | } 65 | }; 66 | 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /include/p2p/Root/NodeInfo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_NODEINFO_HPP 2 | #define P2P_ROOTNETWORK_NODEINFO_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace p2p { 10 | 11 | namespace Root { 12 | 13 | struct NodeInfo { 14 | NodeId id; 15 | std::set endpointSet; 16 | 17 | static NodeInfo Read(BlockingReader& reader); 18 | 19 | inline NodeInfo(NodeId pId, std::set pEndpointSet) 20 | : id(std::move(pId)), endpointSet(std::move(pEndpointSet)) { } 21 | 22 | void writeTo(BlockingWriter& writer) const; 23 | }; 24 | 25 | } 26 | 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/p2p/Root/NodePair.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_NODEPAIR_HPP 2 | #define P2P_ROOTNETWORK_NODEPAIR_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace Root { 10 | 11 | struct NodePair { 12 | NodeId id; 13 | Endpoint endpoint; 14 | 15 | inline NodePair() { } 16 | 17 | inline NodePair(const NodeId& pId, const Endpoint& pEndpoint) 18 | : id(pId), endpoint(pEndpoint) { } 19 | }; 20 | 21 | } 22 | 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/p2p/Root/Packet.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_PACKET_HPP 2 | #define P2P_ROOTNETWORK_PACKET_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace p2p { 13 | 14 | namespace Root { 15 | 16 | struct PacketHeader { 17 | Version version; // 8 bits. 18 | State state; // 2 bits. 19 | bool sub; // 1 bit. 20 | MessageType type; // 4 bits. 21 | PacketLength length; // 16 bits. 22 | RoutineId routine; // 32 bits. 23 | MessageCounter messageCounter; // 64 bits. 24 | NodeId destinationId; // 256 bits. 25 | NetworkId subnetworkId; // If sub == true, 64 bits. 26 | 27 | inline PacketHeader() 28 | : version(VERSION_INVALID), 29 | state(STATE_0), 30 | sub(false), 31 | type(0), 32 | length(0), 33 | routine(0), 34 | messageCounter(0) { } 35 | 36 | }; 37 | 38 | struct PacketSignature { 39 | Buffer signature; 40 | PublicKey publicKey; 41 | }; 42 | 43 | struct Packet { 44 | PacketHeader header; 45 | Buffer payload; 46 | }; 47 | 48 | struct SignedPacket { 49 | Packet packet; 50 | PacketSignature signature; 51 | }; 52 | 53 | PacketHeader ReadPacketHeader(BlockingReader& reader); 54 | 55 | void WritePacketHeader(BlockingWriter& writer, const PacketHeader& header); 56 | 57 | Packet ReadPacket(BlockingReader& reader); 58 | 59 | void WritePacket(BlockingWriter& writer, const Packet& packet); 60 | 61 | PacketSignature ReadSignature(BlockingReader& reader); 62 | 63 | void WriteSignature(BlockingWriter& writer, const PacketSignature& sig); 64 | 65 | } 66 | 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /include/p2p/Root/PacketSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_PACKETSOCKET_HPP 2 | #define P2P_ROOTNETWORK_PACKETSOCKET_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace Root { 17 | 18 | class PacketSocket: public Socket { 19 | public: 20 | PacketSocket(Socket& socket); 21 | 22 | bool isValid() const; 23 | 24 | Event::Source eventSource() const; 25 | 26 | bool receive(Endpoint& endpoint, SignedPacket& packet); 27 | 28 | bool send(const Endpoint& endpoint, const SignedPacket& packet); 29 | 30 | private: 31 | PacketSocket(const PacketSocket&) = delete; 32 | PacketSocket& operator=(PacketSocket) = delete; 33 | 34 | Socket& socket_; 35 | 36 | }; 37 | 38 | } 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/p2p/Root/Parameters.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_PARAMETERS_HPP 2 | #define P2P_ROOTNETWORK_PARAMETERS_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace Root { 9 | 10 | constexpr size_t NETWORK_ID_SIZE_BITS = 64; 11 | constexpr size_t NETWORK_ID_SIZE_BYTES = NETWORK_ID_SIZE_BITS / 8; 12 | 13 | constexpr size_t NODE_ID_SIZE_BITS = 256; 14 | constexpr size_t NODE_ID_SIZE_BYTES = NODE_ID_SIZE_BITS / 8; 15 | 16 | constexpr size_t HEADER_SIZE_BYTES = 48; 17 | constexpr size_t SIGNATURE_SIZE_BYTES = 64; 18 | constexpr size_t PUBLIC_KEY_SIZE_BYTES = 32; 19 | constexpr size_t IDENTITY_SIZE_BYTES = SIGNATURE_SIZE_BYTES + PUBLIC_KEY_SIZE_BYTES; 20 | 21 | // Amount of concurrency for lookups. 22 | constexpr size_t DHT_NUM_PROBES = 3; 23 | 24 | // Maximum number of nodes in each bucket. 25 | constexpr size_t DHT_MAX_BUCKET_SIZE = 20; 26 | 27 | // Maximum number of nodes in a group. 28 | constexpr size_t DHT_MAX_GROUP_SIZE = 20; 29 | 30 | } 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/p2p/Root/PrivateIdentity.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_PRIVATEIDENTITY_HPP 2 | #define P2P_ROOTNETWORK_PRIVATEIDENTITY_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace p2p { 13 | 14 | namespace Root { 15 | 16 | class PrivateIdentity { 17 | public: 18 | PrivateIdentity(Crypt::RandomPool& randomPool, const PrivateKey&, uint64_t packetCount = 0); 19 | 20 | uint64_t nextPacketCount() const; 21 | 22 | const PrivateKey& privateKey() const; 23 | 24 | NodeId id() const; 25 | 26 | PacketSignature sign(const Packet&); 27 | 28 | private: 29 | Crypt::RandomPool& randomPool_; 30 | PrivateKey privateKey_; 31 | uint64_t nextPacketCount_; 32 | 33 | }; 34 | 35 | } 36 | 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/p2p/Root/PublicIdentity.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_PUBLICIDENTITY_HPP 2 | #define P2P_ROOTNETWORK_PUBLICIDENTITY_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace Root { 16 | 17 | class PublicIdentity { 18 | public: 19 | PublicIdentity(const PublicKey&, uint64_t packetCount = 0); 20 | 21 | PublicIdentity(Crypt::RandomPool& randomPool, const PrivateIdentity&); 22 | 23 | uint64_t nextPacketCount() const; 24 | 25 | const PublicKey& publicKey() const; 26 | 27 | NodeId id() const; 28 | 29 | bool verify(const Packet&, const PacketSignature&); 30 | 31 | private: 32 | PublicKey publicKey_; 33 | uint64_t nextPacketCount_; 34 | 35 | }; 36 | 37 | } 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/p2p/Root/RoutineIdGenerator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_ROUTINEIDGENERATOR_HPP 2 | #define P2P_ROOTNETWORK_ROUTINEIDGENERATOR_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace p2p { 9 | 10 | namespace Root { 11 | 12 | /** 13 | * \brief Routine ID Generator. 14 | * 15 | * Thread safe class to generate routine ids. These 16 | * are just 32 bit unsigned values that automatically 17 | * roll over from (2^32 - 1) to 0 (it's assumed routines 18 | * will have ended by the time their ID is re-used). 19 | */ 20 | class RoutineIdGenerator { 21 | public: 22 | RoutineIdGenerator(uint32_t initialValue = 0); 23 | 24 | uint32_t generateId(); 25 | 26 | private: 27 | // Non-copyable. 28 | RoutineIdGenerator(const RoutineIdGenerator&) = delete; 29 | RoutineIdGenerator& operator=(const RoutineIdGenerator&) = delete; 30 | 31 | std::mutex mutex_; 32 | uint32_t nextId_; 33 | 34 | }; 35 | 36 | } 37 | 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/p2p/Root/TransportSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_TRANSPORTSOCKET_HPP 2 | #define P2P_ROOTNETWORK_TRANSPORTSOCKET_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace Root { 16 | 17 | /** 18 | * \brief Transport Socket 19 | * 20 | * Sends/receives root network packets (as raw data) 21 | * through the appropriate underlying transports (e.g. 22 | * UDP or TCP). 23 | */ 24 | class TransportSocket: public Socket { 25 | public: 26 | TransportSocket(Socket& udpSocket); 27 | 28 | bool isValid() const; 29 | 30 | Event::Source eventSource() const; 31 | 32 | bool receive(Endpoint& endpoint, Buffer& buffer); 33 | 34 | bool send(const Endpoint& endpoint, const Buffer& buffer); 35 | 36 | private: 37 | TransportSocket(const TransportSocket&) = delete; 38 | TransportSocket& operator=(TransportSocket) = delete; 39 | 40 | Socket& udpSocket_; 41 | 42 | }; 43 | 44 | } 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/p2p/Root/Types.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_ROOTNETWORK_TYPES_HPP 2 | #define P2P_ROOTNETWORK_TYPES_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace Root { 9 | 10 | enum Version { 11 | VERSION_INVALID = 0, 12 | VERSION_1 = 1 // Currently only one version. 13 | }; 14 | 15 | enum State { 16 | STATE_0 = 0, 17 | STATE_1 = 1, 18 | STATE_2 = 2, 19 | STATE_3 = 3 20 | }; 21 | 22 | using MessageType = uint8_t; 23 | 24 | using PacketLength = uint16_t; 25 | 26 | using RoutineId = uint32_t; 27 | 28 | using MessageCounter = uint64_t; 29 | 30 | } 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/p2p/TCP.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_TCP_HPP 2 | #define P2P_TCP_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/p2p/TCP/Acceptor.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_TCP_ACCEPTOR_HPP 2 | #define P2P_TCP_ACCEPTOR_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace p2p { 9 | 10 | namespace TCP { 11 | 12 | class Acceptor { 13 | public: 14 | Acceptor(uint16_t port); 15 | ~Acceptor(); 16 | 17 | bool accept(Stream& stream); 18 | 19 | private: 20 | // Non-copyable. 21 | Acceptor(const Acceptor&) = delete; 22 | Acceptor& operator=(Acceptor) = delete; 23 | 24 | std::unique_ptr impl_; 25 | 26 | }; 27 | 28 | } 29 | 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/p2p/TCP/Endpoint.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_TCP_ENDPOINT_HPP 2 | #define P2P_TCP_ENDPOINT_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace p2p { 10 | 11 | namespace TCP { 12 | 13 | struct Endpoint { 14 | IP::Address address; 15 | uint16_t port; 16 | 17 | inline Endpoint() 18 | : address(), port(0) { } 19 | 20 | inline Endpoint(const IP::Address& pAddress, uint16_t pPort) 21 | : address(pAddress), port(pPort) { } 22 | 23 | inline bool operator<(const Endpoint& other) const { 24 | return (address != other.address) ? (address < other.address) : (port < other.port); 25 | } 26 | 27 | inline std::string toString() const { 28 | return STR("UDP::Endpoint(address = %s, port = %u)", 29 | address.toString().c_str(), (unsigned) port); 30 | } 31 | 32 | }; 33 | 34 | } 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/p2p/TCP/Resolver.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_TCP_RESOLVER_HPP 2 | #define P2P_TCP_RESOLVER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace p2p { 13 | 14 | namespace TCP { 15 | 16 | class Resolver { 17 | public: 18 | Resolver(); 19 | ~Resolver(); 20 | 21 | boost::optional< std::vector > resolve(const std::string& host, const std::string& service); 22 | 23 | private: 24 | // Non-copyable. 25 | Resolver(const Resolver&) = delete; 26 | Resolver& operator=(Resolver) = delete; 27 | 28 | std::unique_ptr impl_; 29 | 30 | }; 31 | 32 | } 33 | 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/p2p/TCP/Stream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_TCP_STREAM_HPP 2 | #define P2P_TCP_STREAM_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | namespace p2p { 17 | 18 | namespace TCP { 19 | 20 | class Stream: public p2p::IOStream { 21 | public: 22 | Stream(); 23 | ~Stream(); 24 | 25 | bool connect(const TCP::Endpoint& endpoint); 26 | 27 | bool connect(const std::vector& endpointList); 28 | 29 | boost::asio::ip::tcp::socket& getInternal(); 30 | 31 | bool isValid() const; 32 | 33 | Event::Source eventSource() const; 34 | 35 | size_t read(uint8_t* data, size_t size); 36 | 37 | size_t write(const uint8_t* data, size_t size); 38 | 39 | private: 40 | // Non-copyable. 41 | Stream(const Stream&) = delete; 42 | Stream& operator=(Stream) = delete; 43 | 44 | std::unique_ptr impl_; 45 | 46 | 47 | }; 48 | 49 | } 50 | 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/p2p/Transport.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | -------------------------------------------------------------------------------- /include/p2p/Transport/Buffer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_BUFFER_HPP 2 | #define P2P_BUFFER_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | typedef std::vector Buffer; 10 | 11 | //void printBuffer(const Buffer&); 12 | 13 | } 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/p2p/Transport/BufferBuilder.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_BUFFERBUILDER_HPP 2 | #define P2P_BUFFERBUILDER_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace p2p { 11 | 12 | class BufferBuilder: public OStream { 13 | public: 14 | BufferBuilder(Buffer&); 15 | 16 | bool isValid() const; 17 | 18 | Event::Source eventSource() const; 19 | 20 | size_t write(const uint8_t* data, size_t size); 21 | 22 | private: 23 | Buffer& buffer_; 24 | 25 | }; 26 | 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/p2p/Transport/BufferIterator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_BUFFERITERATOR_HPP 2 | #define P2P_BUFFERITERATOR_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace p2p { 11 | 12 | class BufferIterator: public IStream { 13 | public: 14 | BufferIterator(const Buffer& buffer, size_t position = 0); 15 | 16 | size_t position() const; 17 | 18 | size_t remaining() const; 19 | 20 | void set(const Buffer&); 21 | 22 | bool seek(size_t position); 23 | 24 | bool isValid() const; 25 | 26 | Event::Source eventSource() const; 27 | 28 | size_t read(uint8_t* data, size_t size); 29 | 30 | private: 31 | Buffer buffer_; 32 | size_t position_; 33 | 34 | }; 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/p2p/Transport/NullStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_NULLSTREAM_HPP 2 | #define P2P_NULLSTREAM_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace p2p { 10 | 11 | class NullIStream: public IStream { 12 | public: 13 | inline bool isValid() const { 14 | return true; 15 | } 16 | 17 | inline Event::Source eventSource() const { 18 | return Event::Source(); 19 | } 20 | 21 | inline size_t read(uint8_t* data, size_t size) { 22 | // Return zeroes. 23 | memset(data, 0, size); 24 | return size; 25 | } 26 | 27 | }; 28 | 29 | class NullOStream: public OStream { 30 | public: 31 | inline bool isValid() const { 32 | return true; 33 | } 34 | 35 | inline Event::Source eventSource() const { 36 | return Event::Source(); 37 | } 38 | 39 | inline size_t write(const uint8_t*, size_t size) { 40 | return size; 41 | } 42 | 43 | }; 44 | 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/p2p/Transport/Socket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_SOCKET_HPP 2 | #define P2P_SOCKET_HPP 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | template 9 | class Socket { 10 | public: 11 | virtual bool isValid() const = 0; 12 | 13 | virtual Event::Source eventSource() const = 0; 14 | 15 | virtual bool send(const EndpointType& endpoint, const MessageType& message) = 0; 16 | 17 | virtual bool receive(EndpointType& endpoint, MessageType& message) = 0; 18 | 19 | }; 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/p2p/Transport/Stream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_STREAM_HPP 2 | #define P2P_STREAM_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace p2p { 9 | 10 | class BasicStream { 11 | public: 12 | virtual bool isValid() const = 0; 13 | 14 | virtual Event::Source eventSource() const = 0; 15 | 16 | }; 17 | 18 | class IStream: public virtual BasicStream { 19 | public: 20 | virtual size_t read(uint8_t* data, size_t size) = 0; 21 | 22 | }; 23 | 24 | class OStream: public virtual BasicStream { 25 | public: 26 | virtual size_t write(const uint8_t* data, size_t size) = 0; 27 | 28 | }; 29 | 30 | class IOStream: public IStream, public OStream { }; 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/p2p/Transport/StringStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_STRINGSTREAM_HPP 2 | #define P2P_STRINGSTREAM_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace p2p { 11 | 12 | class StringIStream: public IStream { 13 | public: 14 | StringIStream(const std::string&); 15 | 16 | bool isValid() const; 17 | 18 | size_t read(uint8_t* data, size_t size); 19 | 20 | private: 21 | const std::string& string_; 22 | size_t position_; 23 | 24 | }; 25 | 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/p2p/UDP.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_UDP_HPP 2 | #define P2P_UDP_HPP 3 | 4 | #include 5 | #include 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/p2p/UDP/Endpoint.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_UDP_ENDPOINT_HPP 2 | #define P2P_UDP_ENDPOINT_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace UDP { 14 | 15 | struct Endpoint { 16 | IP::Address address; 17 | uint16_t port; 18 | 19 | inline Endpoint() 20 | : address(), port(0) { } 21 | 22 | inline Endpoint(const IP::Address& pAddress, uint16_t pPort) 23 | : address(pAddress), port(pPort) { } 24 | 25 | inline std::string toString() const { 26 | return STR("UDP::Endpoint(address = %s, port = %u)", 27 | address.toString().c_str(), (unsigned) port); 28 | } 29 | 30 | inline bool operator<(const Endpoint& other) const { 31 | return (address != other.address) ? (address < other.address) : (port < other.port); 32 | } 33 | }; 34 | 35 | } 36 | 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/p2p/UDP/Socket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_UDP_SOCKET_HPP 2 | #define P2P_UDP_SOCKET_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace UDP { 14 | 15 | class Socket: public p2p::Socket { 16 | public: 17 | Socket(); 18 | Socket(uint16_t port); 19 | 20 | Socket(Socket&&); 21 | Socket& operator=(Socket&&); 22 | 23 | ~Socket(); 24 | 25 | bool isValid() const; 26 | 27 | Event::Source eventSource() const; 28 | 29 | bool send(const UDP::Endpoint& endpoint, const Buffer& buffer); 30 | 31 | bool receive(UDP::Endpoint& endpoint, Buffer& buffer); 32 | 33 | private: 34 | // Non-copyable. 35 | Socket(const Socket&) = delete; 36 | Socket& operator=(const Socket&) = delete; 37 | 38 | std::unique_ptr impl_; 39 | 40 | }; 41 | 42 | } 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/p2p/Util/String.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_UTIL_STRING_HPP 2 | #define P2P_UTIL_STRING_HPP 3 | 4 | #include 5 | 6 | std::string STR(const char * format, ...) 7 | __attribute__((format(printf, 1, 2))); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/p2p/Util/Timer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_TIMER_HPP 2 | #define P2P_TIMER_HPP 3 | 4 | namespace p2p { 5 | 6 | class Timer { 7 | public: 8 | Timer(); 9 | 10 | double getTime(); 11 | 12 | double getResolution(); 13 | 14 | }; 15 | 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Concurrency) 2 | 3 | add_subdirectory(Crypt) 4 | 5 | add_subdirectory(Event) 6 | 7 | add_subdirectory(FolderSync) 8 | 9 | add_subdirectory(IP) 10 | 11 | add_subdirectory(OFTorrent) 12 | 13 | add_subdirectory(Root) 14 | 15 | add_subdirectory(TCP) 16 | 17 | add_subdirectory(Transport) 18 | 19 | add_subdirectory(UDP) 20 | 21 | add_subdirectory(Util) 22 | 23 | -------------------------------------------------------------------------------- /src/Concurrency/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-concurrency STATIC 2 | Signal.cpp 3 | Thread.cpp 4 | ) 5 | -------------------------------------------------------------------------------- /src/Concurrency/Signal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | namespace p2p { 7 | 8 | Signal::Signal() : isActivated_(false) { } 9 | 10 | void Signal::activate() { 11 | std::lock_guard lock(mutex_); 12 | condition_.notify_all(); 13 | isActivated_ = true; 14 | } 15 | 16 | void Signal::reset() { 17 | std::lock_guard lock(mutex_); 18 | isActivated_ = false; 19 | } 20 | 21 | bool Signal::isActivated() const { 22 | std::lock_guard lock(mutex_); 23 | return isActivated_; 24 | } 25 | 26 | void Signal::wait() { 27 | std::unique_lock lock(mutex_); 28 | 29 | while (!isActivated_) { 30 | condition_.wait(lock); 31 | } 32 | } 33 | 34 | void Signal::cancel() { 35 | std::lock_guard lock(mutex_); 36 | condition_.notify_all(); 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/Concurrency/Thread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace Concurrency { 10 | 11 | namespace { 12 | 13 | void threadFunc(Runnable* runnable) { 14 | runnable->run(); 15 | } 16 | 17 | } 18 | 19 | struct ThreadImpl { 20 | Runnable& runnable; 21 | boost::thread internalThread; 22 | 23 | ThreadImpl(Runnable& pRunnable) 24 | : runnable(pRunnable), 25 | internalThread(boost::bind(threadFunc, &runnable)) { } 26 | }; 27 | 28 | Thread::Thread() 29 | : impl_(nullptr) { } 30 | 31 | Thread::Thread(Runnable& runnable) : impl_(new ThreadImpl(runnable)) { } 32 | 33 | Thread::Thread(Thread&& other) 34 | : impl_(nullptr) { 35 | std::swap(impl_, other.impl_); 36 | } 37 | 38 | Thread& Thread::operator=(Thread&& other) { 39 | std::swap(impl_, other.impl_); 40 | return *this; 41 | } 42 | 43 | Thread::~Thread() { 44 | if (impl_.get() != nullptr) { 45 | impl_->runnable.cancel(); 46 | impl_->internalThread.join(); 47 | } 48 | } 49 | 50 | } 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/Crypt/AutoSeededRandomPool.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace p2p { 10 | 11 | namespace Crypt { 12 | 13 | void AutoSeededRandomPool::generateBlock(uint8_t* data, size_t size) { 14 | return randPool_.GenerateBlock((byte*) data, size); 15 | } 16 | 17 | AutoSeededRandomPool::operator CryptoPP::RandomPool& () { 18 | return randPool_; 19 | } 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/Crypt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-crypt STATIC 2 | AutoSeededRandomPool.cpp 3 | ECDSA/PrivateKey.cpp 4 | ECDSA/PublicKey.cpp 5 | ECDSA/SignStream.cpp 6 | ECDSA/VerifyStream.cpp 7 | Hash/MD5Stream.cpp 8 | Hash/SHA256Stream.cpp 9 | ) 10 | -------------------------------------------------------------------------------- /src/Crypt/ECDSA/PrivateKey.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace Crypt { 16 | 17 | namespace ECDSA { 18 | 19 | PrivateKey::PrivateKey() { } 20 | 21 | PrivateKey::PrivateKey(RandomPool& pool, Curve curve) { 22 | CryptoPP::OID oid; 23 | 24 | switch (curve) { 25 | case brainpoolP256r1: 26 | oid = CryptoPP::ASN1::brainpoolP256r1(); 27 | break; 28 | 29 | case brainpoolP512r1: 30 | oid = CryptoPP::ASN1::brainpoolP512r1(); 31 | break; 32 | 33 | default: 34 | oid = CryptoPP::ASN1::brainpoolP256r1(); 35 | } 36 | 37 | while (true) { 38 | // Black box algorithm: keep generating keys 39 | // until y = min(y, p - y). 40 | privateKey_.Initialize(pool, oid); 41 | CryptoPP::ECDSA::PublicKey publicKey; 42 | privateKey_.MakePublicKey(publicKey); 43 | 44 | if (publicKey.GetPublicElement().y.GetBit(0) == 0) { 45 | break; 46 | } 47 | } 48 | 49 | if (!privateKey_.Validate(pool, 3)) { 50 | throw std::runtime_error("Generated private key is invalid."); 51 | } 52 | } 53 | 54 | PrivateKey::operator CryptoPP::ECDSA::PrivateKey& () { 55 | return privateKey_; 56 | } 57 | 58 | PrivateKey::operator const CryptoPP::ECDSA::PrivateKey& () const { 59 | return privateKey_; 60 | } 61 | 62 | } 63 | 64 | } 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/Crypt/ECDSA/SignStream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace p2p { 19 | 20 | namespace Crypt { 21 | 22 | namespace ECDSA { 23 | 24 | struct SignStreamImpl { 25 | std::string signature; 26 | CryptoPP::ECDSA::Signer signer; 27 | CryptoPP::SignerFilter filter; 28 | 29 | SignStreamImpl(RandomPool& pool, const PrivateKey& privateKey) 30 | : signer(privateKey), 31 | filter(pool, signer, new CryptoPP::StringSink(signature)) { } 32 | }; 33 | 34 | SignStream::SignStream(RandomPool& pool, const PrivateKey& privateKey) 35 | : impl_(new SignStreamImpl(pool, privateKey)) { } 36 | 37 | SignStream::~SignStream() { } 38 | 39 | bool SignStream::isValid() const { 40 | return true; 41 | } 42 | 43 | Event::Source SignStream::eventSource() const { 44 | return Event::Source(); 45 | } 46 | 47 | size_t SignStream::write(const uint8_t* data, size_t size) { 48 | // Apparently this always returns 0, 49 | // which means success... 50 | (void) impl_->filter.Put((const byte*) data, size); 51 | return size; 52 | } 53 | 54 | Buffer SignStream::signature() { 55 | impl_->filter.MessageEnd(); 56 | 57 | return Buffer(impl_->signature.begin(), impl_->signature.end()); 58 | } 59 | 60 | } 61 | 62 | } 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/Crypt/ECDSA/VerifyStream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace Crypt { 14 | 15 | namespace ECDSA { 16 | 17 | struct VerifyStreamImpl { 18 | bool isValid; 19 | CryptoPP::ECDSA::Verifier verifier; 20 | CryptoPP::SignatureVerificationFilter filter; 21 | 22 | VerifyStreamImpl(const PublicKey& publicKey) 23 | : isValid(false), 24 | verifier(publicKey), 25 | filter(verifier, new CryptoPP::ArraySink((byte*) &isValid, sizeof(isValid))) { } 26 | }; 27 | 28 | VerifyStream::VerifyStream(const PublicKey& publicKey, const Buffer& signature) 29 | : impl_(new VerifyStreamImpl(publicKey)) { 30 | impl_->filter.Put(signature.data(), signature.size()); 31 | } 32 | 33 | VerifyStream::~VerifyStream() { } 34 | 35 | bool VerifyStream::isValid() const { 36 | return true; 37 | } 38 | 39 | Event::Source VerifyStream::eventSource() const { 40 | return Event::Source(); 41 | } 42 | 43 | size_t VerifyStream::write(const uint8_t* data, size_t size) { 44 | // Apparently this always returns 0, 45 | // which means success... 46 | (void) impl_->filter.Put((byte*) data, size); 47 | return size; 48 | } 49 | 50 | bool VerifyStream::isSignatureValid() { 51 | impl_->filter.MessageEnd(); 52 | return impl_->isValid; 53 | } 54 | 55 | } 56 | 57 | } 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/Crypt/Hash/MD5Stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | // MD5 is not suitable for security 6 | // purposes, so Crypto++ requires 7 | // this to be defined. 8 | #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | namespace p2p { 19 | 20 | namespace Crypt { 21 | 22 | namespace Hash { 23 | 24 | struct MD5StreamImpl { 25 | std::string digest; 26 | CryptoPP::Weak::MD5 hash; 27 | std::unique_ptr filter; 28 | 29 | inline MD5StreamImpl() 30 | : filter(new CryptoPP::HashFilter(hash, new CryptoPP::StringSink(digest))) { } 31 | }; 32 | 33 | MD5Stream::MD5Stream() : impl_(new MD5StreamImpl()) { } 34 | 35 | MD5Stream::~MD5Stream() { } 36 | 37 | bool MD5Stream::isValid() const { 38 | return true; 39 | } 40 | 41 | Event::Source MD5Stream::eventSource() const { 42 | return Event::Source(); 43 | } 44 | 45 | size_t MD5Stream::write(const uint8_t* data, size_t size) { 46 | // Apparently this always returns 0, 47 | // which means success... 48 | (void) impl_->filter->Put((const byte*) data, size); 49 | return size; 50 | } 51 | 52 | Buffer MD5Stream::calculateDigest() { 53 | impl_->filter->MessageEnd(); 54 | 55 | return Buffer(impl_->digest.begin(), impl_->digest.end()); 56 | } 57 | 58 | } 59 | 60 | } 61 | 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/Crypt/Hash/SHA256Stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace Crypt { 16 | 17 | namespace Hash { 18 | 19 | struct SHA256StreamImpl { 20 | std::string digest; 21 | CryptoPP::SHA256 hash; 22 | std::unique_ptr filter; 23 | 24 | inline SHA256StreamImpl() 25 | : filter(new CryptoPP::HashFilter(hash, new CryptoPP::StringSink(digest))) { } 26 | }; 27 | 28 | SHA256Stream::SHA256Stream() : impl_(new SHA256StreamImpl()) { } 29 | 30 | SHA256Stream::~SHA256Stream() { } 31 | 32 | bool SHA256Stream::isValid() const { 33 | return true; 34 | } 35 | 36 | Event::Source SHA256Stream::eventSource() const { 37 | return Event::Source(); 38 | } 39 | 40 | size_t SHA256Stream::write(const uint8_t* data, size_t size) { 41 | // Apparently this always returns 0, 42 | // which means success... 43 | (void) impl_->filter->Put((const byte*) data, size); 44 | return size; 45 | } 46 | 47 | Buffer SHA256Stream::calculateDigest() { 48 | impl_->filter->MessageEnd(); 49 | 50 | return Buffer(impl_->digest.begin(), impl_->digest.end()); 51 | } 52 | 53 | } 54 | 55 | } 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/Event/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-event STATIC 2 | Generator.cpp 3 | IOService.cpp 4 | MultiGenerator.cpp 5 | Signal.cpp 6 | Source.cpp 7 | Timer.cpp 8 | UnionGenerator.cpp 9 | Wait.cpp 10 | ) 11 | 12 | -------------------------------------------------------------------------------- /src/Event/Generator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include "SourceImpl.hpp" 8 | 9 | namespace p2p { 10 | 11 | namespace Event { 12 | 13 | struct GeneratorImpl: public SourceImpl { 14 | public: 15 | GeneratorImpl(bool initialState) : isActivated_(initialState) { } 16 | 17 | void activate() { 18 | std::lock_guard lock(mutex_); 19 | if (isActivated_) return; 20 | 21 | if (receivers_.empty()) { 22 | // Event is pending. 23 | isActivated_ = true; 24 | return; 25 | } 26 | 27 | // Deliver event immediately. 28 | (*(receivers_.begin()))->notify(); 29 | } 30 | 31 | void addReceiver(Receiver& receiver) { 32 | std::lock_guard lock(mutex_); 33 | receivers_.insert(&receiver); 34 | 35 | if (isActivated_) { 36 | // Deliver pending event. 37 | receiver.notify(); 38 | 39 | // Reset. 40 | isActivated_ = false; 41 | } 42 | } 43 | 44 | void removeReceiver(Receiver& receiver) { 45 | std::lock_guard lock(mutex_); 46 | receivers_.erase(&receiver); 47 | } 48 | 49 | private: 50 | std::mutex mutex_; 51 | bool isActivated_; 52 | std::set receivers_; 53 | 54 | }; 55 | 56 | Generator::Generator(bool initialState) 57 | : impl_(new GeneratorImpl(initialState)) { } 58 | 59 | Generator::~Generator() { } 60 | 61 | Generator::Generator(Generator&& other) 62 | : impl_(std::move(other.impl_)) { } 63 | 64 | Generator& Generator::operator=(Generator&& other) { 65 | std::swap(impl_, other.impl_); 66 | return *this; 67 | } 68 | 69 | void Generator::activate() { 70 | impl_->activate(); 71 | } 72 | 73 | Source Generator::eventSource() const { 74 | return Source(impl_.get()); 75 | } 76 | 77 | } 78 | 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/Event/IOService.cpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_INTERNAL_IOSERVICE_HPP 2 | #define P2P_INTERNAL_IOSERVICE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "IOService.hpp" 11 | 12 | namespace p2p { 13 | 14 | namespace Event { 15 | 16 | IOServiceThread::IOServiceThread(boost::asio::io_service& io, bool wait) 17 | : internalIOService_(io), 18 | work_(new boost::asio::io_service::work(internalIOService_)), 19 | wait_(wait) { } 20 | 21 | void IOServiceThread::run() { 22 | internalIOService_.run(); 23 | } 24 | 25 | void IOServiceThread::cancel() { 26 | work_.reset(); 27 | 28 | if (!wait_) { 29 | internalIOService_.stop(); 30 | } 31 | } 32 | 33 | // wait = true allows operations using the io_service to be terminated gracefully. 34 | IOService::IOService(bool wait) 35 | : internalIOService_(1), 36 | ioThread_(internalIOService_, wait), 37 | thread_(&IOServiceThread::run, &ioThread_) { } 38 | 39 | IOService::~IOService() { 40 | ioThread_.cancel(); 41 | thread_.join(); 42 | } 43 | 44 | void IOService::post(boost::function function) { 45 | internalIOService_.post(function); 46 | } 47 | 48 | IOService::operator boost::asio::io_service& () { 49 | return internalIOService_; 50 | } 51 | 52 | IOService& GetIOService() { 53 | static IOService ioService; 54 | return ioService; 55 | } 56 | 57 | } 58 | 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/Event/IOService.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_EVENT_IOSERVICE_HPP 2 | #define P2P_EVENT_IOSERVICE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace Event { 13 | 14 | class IOServiceThread { 15 | public: 16 | IOServiceThread(boost::asio::io_service& io, bool wait = true); 17 | 18 | void run(); 19 | 20 | void cancel(); 21 | private: 22 | boost::asio::io_service& internalIOService_; 23 | boost::scoped_ptr work_; 24 | bool wait_; 25 | 26 | }; 27 | 28 | class IOService { 29 | public: 30 | // wait = true allows operations using the io_service to be terminated gracefully. 31 | IOService(bool wait = true); 32 | 33 | ~IOService(); 34 | 35 | void post(boost::function function); 36 | 37 | operator boost::asio::io_service& (); 38 | 39 | private: 40 | boost::asio::io_service internalIOService_; 41 | IOServiceThread ioThread_; 42 | std::thread thread_; 43 | 44 | }; 45 | 46 | IOService& GetIOService(); 47 | 48 | } 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/Event/MultiGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "SourceImpl.hpp" 10 | 11 | namespace p2p { 12 | 13 | namespace Event { 14 | 15 | struct MultiGeneratorImpl: public Receiver { 16 | public: 17 | MultiGeneratorImpl(Source source) 18 | : sourceImpl_(source.impl()), nextId_(0ull) { 19 | sourceImpl_->addReceiver(*this); 20 | } 21 | 22 | ~MultiGeneratorImpl() { 23 | sourceImpl_->removeReceiver(*this); 24 | } 25 | 26 | void notify() { 27 | std::lock_guard lock(mutex_); 28 | for (auto& clientGeneratorPair: clientGenerators_) { 29 | clientGeneratorPair.second.activate(); 30 | } 31 | } 32 | 33 | size_t addClient() { 34 | std::lock_guard lock(mutex_); 35 | const auto clientId = nextId_++; 36 | const bool initialState = true; 37 | clientGenerators_.insert(std::make_pair(clientId, Generator(initialState))); 38 | return clientId; 39 | } 40 | 41 | void removeClient(size_t clientId) { 42 | std::lock_guard lock(mutex_); 43 | clientGenerators_.erase(clientId); 44 | } 45 | 46 | Source eventSource(size_t clientId) const { 47 | std::lock_guard lock(mutex_); 48 | return clientGenerators_.at(clientId).eventSource(); 49 | } 50 | 51 | private: 52 | mutable std::mutex mutex_; 53 | SourceImpl* sourceImpl_; 54 | size_t nextId_; 55 | std::map clientGenerators_; 56 | 57 | }; 58 | 59 | MultiGenerator::MultiGenerator(Source source) 60 | : impl_(new MultiGeneratorImpl(source)) { } 61 | 62 | MultiGenerator::~MultiGenerator() { } 63 | 64 | size_t MultiGenerator::addClient() { 65 | return impl_->addClient(); 66 | } 67 | 68 | void MultiGenerator::removeClient(size_t clientId) { 69 | impl_->removeClient(clientId); 70 | } 71 | 72 | Source MultiGenerator::eventSource(size_t clientId) const { 73 | return impl_->eventSource(clientId); 74 | } 75 | 76 | } 77 | 78 | } 79 | 80 | -------------------------------------------------------------------------------- /src/Event/Signal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace Event { 10 | 11 | struct SignalImpl { 12 | std::mutex mutex; 13 | bool isActive; 14 | Generator eventGenerator; 15 | 16 | inline SignalImpl() : 17 | isActive(false) { } 18 | }; 19 | 20 | Signal::Signal() 21 | : impl_(new SignalImpl()) { } 22 | 23 | Signal::~Signal() { } 24 | 25 | Signal::Signal(Signal&& other) 26 | : impl_(std::move(other.impl_)) { } 27 | 28 | Signal& Signal::operator=(Signal&& other) { 29 | std::swap(impl_, other.impl_); 30 | return *this; 31 | } 32 | 33 | void Signal::activate() { 34 | std::lock_guard lock(impl_->mutex); 35 | impl_->isActive = true; 36 | impl_->eventGenerator.activate(); 37 | } 38 | 39 | void Signal::reset() { 40 | std::lock_guard lock(impl_->mutex); 41 | impl_->isActive = false; 42 | impl_->eventGenerator.activate(); 43 | } 44 | 45 | bool Signal::isActive() const { 46 | std::lock_guard lock(impl_->mutex); 47 | return impl_->isActive; 48 | } 49 | 50 | Source Signal::eventSource() const { 51 | return impl_->eventGenerator.eventSource(); 52 | } 53 | 54 | } 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/Event/Source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace p2p { 4 | 5 | namespace Event { 6 | 7 | Source::Source() : impl_(nullptr) { } 8 | 9 | Source::Source(SourceImpl* implPtr) : impl_(implPtr) { } 10 | 11 | SourceImpl* Source::impl() { 12 | return impl_; 13 | } 14 | 15 | } 16 | 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/Event/SourceImpl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef P2P_EVENT_SOURCEIMPL_HPP 2 | #define P2P_EVENT_SOURCEIMPL_HPP 3 | 4 | namespace p2p { 5 | 6 | namespace Event { 7 | 8 | class Receiver { 9 | public: 10 | virtual void notify() = 0; 11 | 12 | }; 13 | 14 | class SourceImpl { 15 | public: 16 | virtual void addReceiver(Receiver& receiver) = 0; 17 | 18 | virtual void removeReceiver(Receiver& receiver) = 0; 19 | 20 | }; 21 | 22 | } 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/Event/UnionGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "SourceImpl.hpp" 9 | 10 | namespace p2p { 11 | 12 | namespace Event { 13 | 14 | struct UnionGeneratorImpl: public Receiver { 15 | public: 16 | UnionGeneratorImpl(std::vector sourceList) 17 | : sourceList_(std::move(sourceList)) { 18 | for (auto source: sourceList_) { 19 | source.impl()->addReceiver(*this); 20 | } 21 | } 22 | 23 | ~UnionGeneratorImpl() { 24 | for (size_t i = 0; i < sourceList_.size(); i++) { 25 | sourceList_.at(sourceList_.size() - 1 - i).impl()->removeReceiver(*this); 26 | } 27 | } 28 | 29 | void notify() { 30 | clientGenerator_.activate(); 31 | } 32 | 33 | Source eventSource() const { 34 | return clientGenerator_.eventSource(); 35 | } 36 | 37 | private: 38 | std::vector sourceList_; 39 | Generator clientGenerator_; 40 | 41 | }; 42 | 43 | UnionGenerator::UnionGenerator(std::vector sourceList) 44 | : impl_(new UnionGeneratorImpl(std::move(sourceList))) { } 45 | 46 | UnionGenerator::~UnionGenerator() { } 47 | 48 | Source UnionGenerator::eventSource() const { 49 | return impl_->eventSource(); 50 | } 51 | 52 | } 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/FolderSync/Block.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace p2p { 9 | 10 | namespace FolderSync { 11 | 12 | Block Block::Zero() { 13 | Block block; 14 | block.data_.resize(BLOCK_SIZE, 0x00); 15 | return std::move(block); 16 | } 17 | 18 | Block::Block(Block&& block) noexcept 19 | : data_(std::move(block.data_)) { } 20 | 21 | uint8_t* Block::data() { 22 | return data_.data(); 23 | } 24 | 25 | const uint8_t* Block::data() const { 26 | return data_.data(); 27 | } 28 | 29 | size_t Block::size() const { 30 | return BLOCK_SIZE; 31 | } 32 | 33 | Block Block::copy() const { 34 | Block copyBlock; 35 | copyBlock.data_ = data_; 36 | return std::move(copyBlock); 37 | } 38 | 39 | Block::Block() { } 40 | 41 | } 42 | 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/FolderSync/BlockCache.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace FolderSync { 10 | 11 | BlockCache::BlockCache(BlockStore& blockStore) 12 | : map_(blockStore) { } 13 | 14 | BlockCache::~BlockCache() { 15 | flush(); 16 | } 17 | 18 | const Block& BlockCache::getReadBlock(const BlockPath& path) const { 19 | return map_.loadBlock(path).block; 20 | } 21 | 22 | Block& BlockCache::getWriteBlock(const BlockPath& path) { 23 | auto& blockInfo = map_.loadBlock(path); 24 | blockInfo.isDirty = true; 25 | return blockInfo.block; 26 | } 27 | 28 | void BlockCache::flush() { 29 | map_.flush(); 30 | } 31 | 32 | } 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/FolderSync/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-foldersync STATIC 2 | Block.cpp 3 | BlockCache.cpp 4 | BlockCacheMap.cpp 5 | BlockId.cpp 6 | BlockPath.cpp 7 | Directory.cpp 8 | FileDatabase.cpp 9 | Journal.cpp 10 | MemDatabase.cpp 11 | Node.cpp 12 | NodeBlockStore.cpp 13 | NodeReader.cpp 14 | NodeWriter.cpp 15 | ) 16 | 17 | -------------------------------------------------------------------------------- /src/FolderSync/Journal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace FolderSync { 9 | 10 | Journal::Journal() { } 11 | 12 | void Journal::addNewRoot(const BlockId& blockId) { 13 | entries_.push_back(blockId); 14 | } 15 | 16 | const BlockId& Journal::rootId() const { 17 | return entries_.back(); 18 | } 19 | 20 | } 21 | 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/FolderSync/MemDatabase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace p2p { 9 | 10 | namespace FolderSync { 11 | 12 | MemDatabase::MemDatabase() { 13 | storeBlock(BlockId(), Block::Zero()); 14 | } 15 | 16 | MemDatabase::~MemDatabase() { } 17 | 18 | Block MemDatabase::loadBlock(const BlockId& id) const { 19 | return data_.at(id).copy(); 20 | } 21 | 22 | void MemDatabase::storeBlock(const BlockId& id, Block data) { 23 | data_.emplace(id, std::move(data)); 24 | } 25 | 26 | } 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/FolderSync/NodeBlockStore.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace FolderSync { 17 | 18 | NodeBlockStore::NodeBlockStore(Database& database, const BlockId& initialRootId) 19 | : database_(database), rootId_(initialRootId) { } 20 | 21 | NodeBlockStore::~NodeBlockStore() { } 22 | 23 | const BlockId& NodeBlockStore::rootId() const { 24 | return rootId_; 25 | } 26 | 27 | Block NodeBlockStore::getRoot() const { 28 | return database_.loadBlock(rootId_); 29 | } 30 | 31 | void NodeBlockStore::setRoot(Block block) { 32 | rootId_ = BlockId::Generate(block); 33 | return database_.storeBlock(rootId_, std::move(block)); 34 | } 35 | 36 | Block NodeBlockStore::getBlock(const BlockPath& path, const Block& parentBlock) const { 37 | BlockReader reader(parentBlock, NodeBlockIdOffset(path)); 38 | const auto blockId = BlockId::FromReader(reader); 39 | 40 | return database_.loadBlock(blockId); 41 | } 42 | 43 | void NodeBlockStore::setBlock(const BlockPath& path, Block& parentBlock, Block block) { 44 | const auto blockId = BlockId::Generate(block); 45 | database_.storeBlock(blockId, std::move(block)); 46 | 47 | BlockWriter writer(parentBlock, NodeBlockIdOffset(path)); 48 | blockId.writeTo(writer); 49 | } 50 | 51 | } 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/FolderSync/NodeReader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace p2p { 15 | 16 | namespace FolderSync { 17 | 18 | NodeReader::NodeReader(const Node& node, NodeOffset initialPosition) 19 | : node_(node), position_(0) { 20 | seek(initialPosition); 21 | } 22 | 23 | NodeOffset NodeReader::position() const { 24 | return position_; 25 | } 26 | 27 | void NodeReader::seek(NodeOffset newPosition) { 28 | if (newPosition > node_.size()) { 29 | throw std::runtime_error("Seek position exceeds node size."); 30 | } 31 | 32 | position_ = newPosition; 33 | } 34 | 35 | void NodeReader::readAll(uint8_t* data, size_t size) { 36 | const size_t readSize = node_.read(position_, data, size); 37 | assert(readSize <= size); 38 | if (readSize < size) { 39 | throw std::runtime_error("Reached end of node data."); 40 | } 41 | position_ += size; 42 | } 43 | 44 | } 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/FolderSync/NodeWriter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace FolderSync { 14 | 15 | NodeWriter::NodeWriter(Node& node, NodeOffset initialPosition) 16 | : node_(node), position_(0) { 17 | seek(initialPosition); 18 | } 19 | 20 | NodeOffset NodeWriter::position() const { 21 | return position_; 22 | } 23 | 24 | void NodeWriter::seek(NodeOffset newPosition) { 25 | if (newPosition > node_.size()) { 26 | throw std::runtime_error("Seek position exceeds node size."); 27 | } 28 | 29 | position_ = newPosition; 30 | } 31 | 32 | void NodeWriter::writeAll(const uint8_t* data, size_t size) { 33 | node_.write(position_, data, size); 34 | position_ += size; 35 | } 36 | 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/IP/Address.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace p2p { 5 | 6 | namespace IP { 7 | 8 | AddressImplType Address::ToImpl(const Address& address) { 9 | switch (address.version) { 10 | case v4: 11 | return V4Address::ToImpl(address.v4Address); 12 | 13 | case v6: 14 | return V6Address::ToImpl(address.v6Address); 15 | } 16 | 17 | return AddressImplType(); 18 | } 19 | 20 | Address Address::FromImpl(const AddressImplType& addressImpl) { 21 | if (addressImpl.is_v4()) { 22 | Address address; 23 | address.version = v4; 24 | address.v4Address = V4Address::FromImpl(addressImpl.to_v4()); 25 | return address; 26 | } else { 27 | Address address; 28 | address.version = v6; 29 | address.v6Address = V6Address::FromImpl(addressImpl.to_v6()); 30 | return address; 31 | } 32 | } 33 | 34 | Address::Address() { } 35 | 36 | Address::Address(const V4Address& pAddress) 37 | : version(v4), v4Address(pAddress) { } 38 | 39 | Address::Address(const V6Address& pAddress) 40 | : version(v6), v6Address(pAddress) { } 41 | 42 | bool Address::operator==(const Address& other) const { 43 | return version == other.version && 44 | ((version == v4) ? 45 | (v4Address == other.v4Address) : 46 | (v6Address == other.v6Address) 47 | ); 48 | } 49 | 50 | bool Address::operator!=(const Address& other) const { 51 | return !(*this == other); 52 | } 53 | 54 | bool Address::operator<(const Address& other) const { 55 | return (version != other.version) ? (version < other.version) : 56 | ((version == v4) ? 57 | (v4Address < other.v4Address) : 58 | (v6Address < other.v6Address) 59 | ); 60 | } 61 | 62 | std::string Address::toString() const { 63 | if (version == v4) { 64 | return STR("IPv4Address(%s)", 65 | v4Address.toString().c_str()); 66 | } else { 67 | return STR("IPv6Address(%s)", 68 | v6Address.toString().c_str()); 69 | } 70 | } 71 | 72 | } 73 | 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/IP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-ip STATIC Address.cpp V4Address.cpp V6Address.cpp) 2 | -------------------------------------------------------------------------------- /src/IP/V4Address.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace IP { 9 | 10 | V4AddressImplType V4Address::ToImpl(const V4Address& address) { 11 | return V4AddressImplType(address.data); 12 | } 13 | 14 | V4Address V4Address::FromImpl(const V4AddressImplType& addressImpl) { 15 | V4Address address; 16 | address.data = addressImpl.to_bytes(); 17 | return address; 18 | } 19 | 20 | V4Address V4Address::Any() { 21 | return V4Address::FromImpl(boost::asio::ip::address_v4::any()); 22 | } 23 | 24 | V4Address V4Address::Broadcast() { 25 | return V4Address::FromImpl(boost::asio::ip::address_v4::broadcast()); 26 | } 27 | 28 | V4Address V4Address::Localhost() { 29 | return V4Address::FromImpl(boost::asio::ip::address_v4::loopback()); 30 | } 31 | 32 | V4Address V4Address::Netmask(const V4Address& address) { 33 | return V4Address::FromImpl(boost::asio::ip::address_v4::netmask(V4Address::ToImpl(address))); 34 | } 35 | 36 | bool V4Address::operator==(const V4Address& other) const { 37 | return data == other.data; 38 | } 39 | 40 | bool V4Address::operator<(const V4Address& other) const { 41 | return data < other.data; 42 | } 43 | 44 | std::string V4Address::toString() const { 45 | return STR("%u.%u.%u.%u", 46 | (unsigned) data.at(0), 47 | (unsigned) data.at(1), 48 | (unsigned) data.at(2), 49 | (unsigned) data.at(3)); 50 | } 51 | 52 | } 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/IP/V6Address.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace IP { 9 | 10 | V6AddressImplType V6Address::ToImpl(const V6Address& address) { 11 | return V6AddressImplType(address.data); 12 | } 13 | 14 | V6Address V6Address::FromImpl(const V6AddressImplType& addressImpl) { 15 | V6Address address; 16 | address.data = addressImpl.to_bytes(); 17 | return address; 18 | } 19 | 20 | V6Address V6Address::Any() { 21 | return V6Address::FromImpl(boost::asio::ip::address_v6::any()); 22 | } 23 | 24 | V6Address V6Address::Localhost() { 25 | return V6Address::FromImpl(boost::asio::ip::address_v6::loopback()); 26 | } 27 | 28 | bool V6Address::operator==(const V6Address& other) const { 29 | return data == other.data; 30 | } 31 | 32 | bool V6Address::operator<(const V6Address& other) const { 33 | return data < other.data; 34 | } 35 | 36 | std::string V6Address::toString() const { 37 | return ToImpl(*this).to_string(); 38 | } 39 | 40 | } 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/OFTorrent/BlockStream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace p2p { 7 | 8 | namespace OFTorrent { 9 | 10 | BlockStream::BlockStream(OutputStreamGenerator& generator, BlockSize size) 11 | : generator_(generator), blockPos_(0), blockSize_(size) { 12 | stream_ = &(generator_.getNextOutputStream()); 13 | } 14 | 15 | bool BlockStream::isValid() const { 16 | return stream_->isValid(); 17 | } 18 | 19 | Event::Source BlockStream::eventSource() const { 20 | return stream_->eventSource(); 21 | } 22 | 23 | size_t BlockStream::write(const uint8_t* data, size_t size) { 24 | const size_t maxWriteSize = std::min(size, blockSize_ - blockPos_); 25 | 26 | const size_t writeSize = stream_->write(data, maxWriteSize); 27 | 28 | blockPos_ += writeSize; 29 | if (blockPos_ == blockSize_) { 30 | stream_ = &(generator_.getNextOutputStream()); 31 | blockPos_ = 0; 32 | } 33 | 34 | return writeSize; 35 | } 36 | 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/OFTorrent/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-oftorrent STATIC BlockStream.cpp XORStream.cpp) 2 | -------------------------------------------------------------------------------- /src/OFTorrent/XORStream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace OFTorrent { 14 | 15 | XORStream::XORStream(IStream& source0, IStream& source1) : source0_(source0), source1_(source1) { } 16 | 17 | bool XORStream::isValid() const { 18 | return source0_.isValid() && source1_.isValid(); 19 | } 20 | 21 | Event::Source XORStream::eventSource() const { 22 | // TODO: get events from both source streams! 23 | return source0_.eventSource(); 24 | } 25 | 26 | size_t XORStream::read(uint8_t* data, size_t size) { 27 | const size_t source0Size = source0_.readMax(); 28 | const size_t source1Size = source1_.readMax(); 29 | 30 | const size_t readSize = std::min(std::min(source0Size, source1Size), size); 31 | 32 | for (size_t i = 0; i < readSize; i++) { 33 | data[i] = source0_[i] ^ source1_[i]; 34 | } 35 | 36 | return readSize; 37 | } 38 | 39 | } 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/Root/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-rootnetwork STATIC 2 | AuthenticatedSocket.cpp 3 | Endpoint.cpp 4 | EndpointMapSocket.cpp 5 | NetworkId.cpp 6 | NodeDatabase.cpp 7 | NodeDetectSocket.cpp 8 | NodeId.cpp 9 | NodeInfo.cpp 10 | Packet.cpp 11 | PacketSocket.cpp 12 | PrivateIdentity.cpp 13 | PublicIdentity.cpp 14 | RoutineIdGenerator.cpp 15 | TransportSocket.cpp 16 | 17 | Core/RPCClient.cpp 18 | Core/RPCMessage.cpp 19 | Core/RPCServer.cpp 20 | Core/Service.cpp 21 | 22 | DHT/RPCClient.cpp 23 | DHT/RPCMessage.cpp 24 | DHT/RPCServer.cpp 25 | DHT/Service.cpp 26 | ) 27 | -------------------------------------------------------------------------------- /src/Root/Core/Service.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | namespace p2p { 23 | 24 | namespace Root { 25 | 26 | namespace Core { 27 | 28 | Service::Service(Socket& socket, RoutineIdGenerator& routineIdGenerator) 29 | : socket_(socket), multiplexHost_(socket), 30 | clientSocket_(multiplexHost_), 31 | serverSocket_(multiplexHost_), 32 | client_(clientSocket_, routineIdGenerator), 33 | server_(serverSocket_), 34 | unionGenerator_({ client_.eventSource(), server_.eventSource() }) { } 35 | 36 | Service::~Service() { } 37 | 38 | Event::Source Service::eventSource() const { 39 | return unionGenerator_.eventSource(); 40 | } 41 | 42 | bool Service::processMessage() { 43 | return client_.processResponse() || server_.processRequest(); 44 | } 45 | 46 | void Service::addNetwork(const std::string& networkName) { 47 | server_.addNetwork(networkName); 48 | } 49 | 50 | RPC::Operation Service::identify(const Endpoint& endpoint) { 51 | return client_.identify(endpoint); 52 | } 53 | 54 | RPC::Operation Service::ping(const Endpoint& endpoint, const NodeId& nodeId) { 55 | return client_.ping(endpoint, nodeId); 56 | } 57 | 58 | RPC::Operation> Service::queryNetworks(const Endpoint& endpoint, const NodeId& nodeId) { 59 | return client_.queryNetworks(endpoint, nodeId); 60 | } 61 | 62 | } 63 | 64 | } 65 | 66 | } 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/Root/DHT/RPCFindSocket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | namespace p2p { 22 | 23 | namespace Root { 24 | 25 | namespace DHT { 26 | 27 | RPCFindSocket::RPCFindSocket(Socket& socket, RoutineIdGenerator& routineIdGenerator) 28 | : socket_(socket), routineIdGenerator_(routineIdGenerator) { } 29 | 30 | RPCFindSocket::~RPCFindSocket() { } 31 | 32 | Event::Source RPCFindSocket::eventSource() const { 33 | return socket_.eventSource(); 34 | } 35 | 36 | void RPCFindSocket::sendFind(const NodeId& destId, const NodeId& searchId) { 37 | const auto routineId = routineIdGenerator_.generateId(); 38 | socket_.send(destId, RPCMessage::GetNearestNodesRequest(searchId).createMessage(routineId); 39 | } 40 | 41 | bool RPCFindSocket::receiveFind(NodeId& sourceId, std::vector& group) { 42 | Message message; 43 | const bool result = socket_.receive(sourceId, message); 44 | if (!result) return false; 45 | 46 | if (!message.subnetwork || *(message.subnetwork) != NetworkId::Generate("p2p.rootdht")) { 47 | return false; 48 | } 49 | } 50 | 51 | } 52 | 53 | } 54 | 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/Root/DHT/Service.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | namespace p2p { 24 | 25 | namespace Root { 26 | 27 | namespace DHT { 28 | 29 | Service::Service(Socket& socket, RoutineIdGenerator& routineIdGenerator, ServerDelegate& delegate) 30 | : socket_(socket), multiplexHost_(socket), 31 | clientSocket_(multiplexHost_), 32 | serverSocket_(multiplexHost_), 33 | client_(clientSocket_, routineIdGenerator), 34 | server_(serverSocket_, delegate), 35 | unionGenerator_({ client_.eventSource(), server_.eventSource() }) { } 36 | 37 | Service::~Service() { } 38 | 39 | Event::Source Service::eventSource() const { 40 | return unionGenerator_.eventSource(); 41 | } 42 | 43 | bool Service::processMessage() { 44 | return client_.processResponse() || server_.processRequest(); 45 | } 46 | 47 | RPC::Operation> Service::getNearestNodes(const NodeId& destId, const NodeId& targetId) { 48 | return client_.getNearestNodes(destId, targetId); 49 | } 50 | 51 | RPC::Operation Service::subscribe(const NodeId& destId, const NodeId& targetId, const std::vector& myEndpoints) { 52 | return client_.subscribe(destId, targetId, myEndpoints); 53 | } 54 | 55 | RPC::Operation> Service::getSubscribers(const NodeId& destId, const NodeId& targetId) { 56 | return client_.getSubscribers(destId, targetId); 57 | } 58 | 59 | } 60 | 61 | } 62 | 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/Root/EndpointMapSocket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace p2p { 13 | 14 | namespace Root { 15 | 16 | EndpointMapSocket::EndpointMapSocket(Socket& socket, NodeDatabase& database) 17 | : socket_(socket), database_(database) { } 18 | 19 | bool EndpointMapSocket::isValid() const { 20 | return socket_.isValid(); 21 | } 22 | 23 | Event::Source EndpointMapSocket::eventSource() const { 24 | return socket_.eventSource(); 25 | } 26 | 27 | bool EndpointMapSocket::receive(NodeId& nodeId, Message& message) { 28 | NodePair nodePair; 29 | if (!socket_.receive(nodePair, message)) { 30 | return false; 31 | } 32 | 33 | nodeId = nodePair.id; 34 | 35 | if (!database_.isKnownId(nodeId)) { 36 | return false; 37 | } 38 | 39 | auto& nodeEntry = database_.nodeEntry(nodeId); 40 | nodeEntry.endpointSet.insert(nodePair.endpoint); 41 | 42 | return true; 43 | } 44 | 45 | bool EndpointMapSocket::send(const NodeId& nodeId, const Message& message) { 46 | if (!database_.isKnownId(nodeId)) { 47 | return false; 48 | } 49 | 50 | const auto& nodeEntry = database_.nodeEntry(nodeId); 51 | const auto destinationId = nodeEntry.identity.id(); 52 | 53 | // Broadcast message to all endpoints. 54 | for (const auto& endpoint: nodeEntry.endpointSet) { 55 | (void) socket_.send(NodePair(destinationId, endpoint), message); 56 | } 57 | 58 | return true; 59 | } 60 | 61 | } 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/Root/NodeDatabase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace p2p { 9 | 10 | namespace Root { 11 | 12 | NodeDatabase::NodeDatabase() { } 13 | 14 | bool NodeDatabase::isKnownId(const NodeId& id) const { 15 | return map_.find(id) != map_.end(); 16 | } 17 | 18 | void NodeDatabase::addNode(const NodeId& id, NodeEntry pNodeEntry) { 19 | map_.emplace(id, std::move(pNodeEntry)); 20 | } 21 | 22 | NodeEntry& NodeDatabase::nodeEntry(const NodeId& id) { 23 | return map_.at(id); 24 | } 25 | 26 | const NodeEntry& NodeDatabase::nodeEntry(const NodeId& id) const { 27 | return map_.at(id); 28 | } 29 | 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/Root/NodeDetectSocket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace Root { 10 | 11 | NodeDetectSocket::NodeDetectSocket(Socket& socket, NodeDetectDelegate& delegate) 12 | : socket_(socket), delegate_(delegate) { } 13 | 14 | bool NodeDetectSocket::isValid() const { 15 | return socket_.isValid(); 16 | } 17 | 18 | Event::Source NodeDetectSocket::eventSource() const { 19 | return socket_.eventSource(); 20 | } 21 | 22 | bool NodeDetectSocket::receive(NodePair& nodePair, Message& message) { 23 | if (!socket_.receive(nodePair, message)) { 24 | return false; 25 | } 26 | 27 | delegate_.detectedNodePair(nodePair); 28 | 29 | return true; 30 | } 31 | 32 | bool NodeDetectSocket::send(const NodePair& nodePair, const Message& message) { 33 | return socket_.send(nodePair, message); 34 | } 35 | 36 | } 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/Root/NodeInfo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace p2p { 10 | 11 | namespace Root { 12 | 13 | NodeInfo NodeInfo::Read(BlockingReader& reader) { 14 | const auto nodeId = NodeId::FromReader(reader); 15 | const auto endpointCount = Binary::ReadUint16(reader); 16 | 17 | std::set nodeEndpoints; 18 | for (uint16_t i = 0; i < endpointCount; i++) { 19 | nodeEndpoints.insert(Endpoint::Read(reader)); 20 | } 21 | 22 | return NodeInfo(nodeId, std::move(nodeEndpoints)); 23 | } 24 | 25 | void NodeInfo::writeTo(BlockingWriter& writer) const { 26 | id.writeTo(writer); 27 | Binary::WriteUint16(writer, endpointSet.size()); 28 | for (const auto& endpoint: endpointSet) { 29 | endpoint.writeTo(writer); 30 | } 31 | } 32 | 33 | } 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/Root/PacketSocket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace Root { 16 | 17 | PacketSocket::PacketSocket(Socket& socket) 18 | : socket_(socket) { } 19 | 20 | bool PacketSocket::isValid() const { 21 | return socket_.isValid(); 22 | } 23 | 24 | Event::Source PacketSocket::eventSource() const { 25 | return socket_.eventSource(); 26 | } 27 | 28 | bool PacketSocket::receive(Endpoint& endpoint, SignedPacket& signedPacket) { 29 | Buffer buffer; 30 | 31 | if (!socket_.receive(endpoint, buffer)) { 32 | return false; 33 | } 34 | 35 | BufferIterator bufferIterator(buffer); 36 | BinaryIStream blockingReader(bufferIterator); 37 | signedPacket.packet = ReadPacket(blockingReader); 38 | signedPacket.signature = ReadSignature(blockingReader); 39 | return true; 40 | } 41 | 42 | bool PacketSocket::send(const Endpoint& endpoint, const SignedPacket& signedPacket) { 43 | Buffer buffer; 44 | BufferBuilder bufferBuilder(buffer); 45 | BinaryOStream blockingWriter(bufferBuilder); 46 | WritePacket(blockingWriter, signedPacket.packet); 47 | WriteSignature(blockingWriter, signedPacket.signature); 48 | return socket_.send(endpoint, buffer); 49 | } 50 | 51 | } 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/Root/PrivateIdentity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace p2p { 12 | 13 | namespace Root { 14 | 15 | PrivateIdentity::PrivateIdentity(Crypt::RandomPool& randomPool, const PrivateKey& pPrivateKey, uint64_t pPacketCount) 16 | : randomPool_(randomPool), privateKey_(pPrivateKey), nextPacketCount_(pPacketCount) { } 17 | 18 | uint64_t PrivateIdentity::nextPacketCount() const { 19 | return nextPacketCount_; 20 | } 21 | 22 | const PrivateKey& PrivateIdentity::privateKey() const { 23 | return privateKey_; 24 | } 25 | 26 | NodeId PrivateIdentity::id() const { 27 | return NodeId::Generate(PublicKey(randomPool_, privateKey_)); 28 | } 29 | 30 | PacketSignature PrivateIdentity::sign(const Packet& packet) { 31 | // Advance packet count to prevent replays. 32 | nextPacketCount_++; 33 | 34 | Crypt::ECDSA::SignStream signStream(randomPool_, privateKey_); 35 | BinaryOStream binStream(signStream); 36 | WritePacket(binStream, packet); 37 | 38 | PacketSignature sig; 39 | sig.signature = signStream.signature(); 40 | sig.publicKey = PublicKey(randomPool_, privateKey_); 41 | 42 | assert(sig.signature.size() == SIGNATURE_SIZE_BYTES); 43 | return sig; 44 | } 45 | 46 | } 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/Root/PublicIdentity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace Root { 16 | 17 | PublicIdentity::PublicIdentity(const PublicKey& pPublicKey, uint64_t packetCount) 18 | : publicKey_(pPublicKey), nextPacketCount_(packetCount) { } 19 | 20 | PublicIdentity::PublicIdentity(Crypt::RandomPool& randomPool, const PrivateIdentity& identity) 21 | : nextPacketCount_(identity.nextPacketCount()) { 22 | publicKey_ = PublicKey(randomPool, identity.privateKey()); 23 | } 24 | 25 | uint64_t PublicIdentity::nextPacketCount() const { 26 | return nextPacketCount_; 27 | } 28 | 29 | const PublicKey& PublicIdentity::publicKey() const { 30 | return publicKey_; 31 | } 32 | 33 | NodeId PublicIdentity::id() const { 34 | return NodeId::Generate(publicKey_); 35 | } 36 | 37 | bool PublicIdentity::verify(const Packet& packet, const PacketSignature& sig) { 38 | assert(sig.signature.size() == SIGNATURE_SIZE_BYTES); 39 | 40 | if (packet.header.messageCounter < nextPacketCount_) { 41 | return false; 42 | } 43 | 44 | nextPacketCount_ = packet.header.messageCounter + 1; 45 | 46 | Crypt::ECDSA::VerifyStream verifyStream(publicKey_, sig.signature); 47 | BinaryOStream binStream(verifyStream); 48 | WritePacket(binStream, packet); 49 | 50 | return verifyStream.isSignatureValid(); 51 | } 52 | 53 | } 54 | 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/Root/RoutineIdGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace Root { 10 | 11 | RoutineIdGenerator::RoutineIdGenerator(uint32_t initialValue) 12 | : nextId_(initialValue) { } 13 | 14 | uint32_t RoutineIdGenerator::generateId() { 15 | std::lock_guard lock(mutex_); 16 | return nextId_++; 17 | } 18 | 19 | } 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/Root/TransportSocket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace p2p { 11 | 12 | namespace Root { 13 | 14 | TransportSocket::TransportSocket(Socket& udpSocket) 15 | : udpSocket_(udpSocket) { } 16 | 17 | bool TransportSocket::isValid() const { 18 | return udpSocket_.isValid(); 19 | } 20 | 21 | Event::Source TransportSocket::eventSource() const { 22 | return udpSocket_.eventSource(); 23 | } 24 | 25 | bool TransportSocket::receive(Endpoint& endpoint, Buffer& buffer) { 26 | UDP::Endpoint udpEndpoint; 27 | 28 | // TODO: add support for other endpoints. 29 | if (!udpSocket_.receive(udpEndpoint, buffer)) { 30 | return false; 31 | } 32 | 33 | endpoint.kind = Endpoint::UDPIPV6; 34 | endpoint.udpEndpoint = udpEndpoint; 35 | return true; 36 | } 37 | 38 | bool TransportSocket::send(const Endpoint& endpoint, const Buffer& buffer) { 39 | assert(endpoint.kind == Endpoint::UDPIPV6); 40 | // TODO: add support for other endpoints. 41 | return udpSocket_.send(endpoint.udpEndpoint, buffer); 42 | } 43 | 44 | } 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/TCP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-tcp STATIC Acceptor.cpp Resolver.cpp Stream.cpp) 2 | -------------------------------------------------------------------------------- /src/TCP/Resolver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include "../Event/IOService.hpp" 14 | 15 | namespace p2p { 16 | 17 | namespace TCP { 18 | 19 | struct ResolverImpl { 20 | boost::asio::ip::tcp::resolver resolver; 21 | 22 | inline ResolverImpl() 23 | : resolver(Event::GetIOService()) { } 24 | }; 25 | 26 | namespace { 27 | 28 | void resolveCallback(Signal* signal, bool* resolveResult, std::vector* endpointList, 29 | const boost::system::error_code& ec, boost::asio::ip::tcp::resolver::iterator iterator) { 30 | 31 | if (!ec) { 32 | for (boost::asio::ip::tcp::resolver::iterator end; iterator != end; ++iterator) { 33 | const boost::asio::ip::tcp::endpoint& endpointImpl = *iterator; 34 | 35 | TCP::Endpoint endpoint; 36 | endpoint.address = IP::Address::FromImpl(endpointImpl.address()); 37 | endpoint.port = endpointImpl.port(); 38 | endpointList->push_back(endpoint); 39 | } 40 | } 41 | 42 | *resolveResult = !bool(ec); 43 | signal->activate(); 44 | } 45 | 46 | } 47 | 48 | Resolver::Resolver() : impl_(new ResolverImpl()) { } 49 | 50 | Resolver::~Resolver() { } 51 | 52 | // TODO: make this non-blocking! 53 | boost::optional< std::vector > Resolver::resolve(const std::string& host, const std::string& service) { 54 | boost::asio::ip::tcp::resolver::query query(host, service); 55 | 56 | bool resolveResult = false; 57 | 58 | Signal signal; 59 | 60 | std::vector endpointList; 61 | 62 | impl_->resolver.async_resolve(query, boost::bind(resolveCallback, &signal, &resolveResult, &endpointList, _1, _2)); 63 | 64 | signal.wait(); 65 | 66 | return resolveResult ? boost::make_optional(endpointList) : boost::none; 67 | } 68 | 69 | } 70 | 71 | } 72 | 73 | -------------------------------------------------------------------------------- /src/Transport/Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace p2p { 4 | 5 | /*Buffer::Buffer(){ } 6 | 7 | Buffer::Buffer(const uint8_t * data, size_t size) 8 | : data_(data, data + size){ } 9 | 10 | Buffer::Buffer(const Buffer& buffer) 11 | : data_(buffer.data_){ } 12 | 13 | std::vector& Buffer::data(){ 14 | return data_; 15 | } 16 | 17 | size_t Buffer::size() const { 18 | return data_.size(); 19 | } 20 | 21 | std::string getBufferString(const boost::shared_ptr& ptr){ 22 | std::ostringstream stream; 23 | if(ptr->left() == ptr){ 24 | stream << "Leaf(" << ptr->size() << ")"; 25 | }else{ 26 | stream << "Node(" << getBufferString(ptr->left()) << ", " << getBufferString(ptr->right()) << ")"; 27 | } 28 | return stream.str(); 29 | } 30 | 31 | void printBuffer(const Buffer& buffer){ 32 | std::cout << getBufferString(buffer.tree()) << std::endl; 33 | }*/ 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/Transport/BufferBuilder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace p2p { 7 | 8 | BufferBuilder::BufferBuilder(Buffer& buffer) : buffer_(buffer) { } 9 | 10 | bool BufferBuilder::isValid() const { 11 | return true; 12 | } 13 | 14 | Event::Source BufferBuilder::eventSource() const { 15 | return Event::Source(); 16 | } 17 | 18 | size_t BufferBuilder::write(const uint8_t* data, size_t size) { 19 | buffer_.reserve(buffer_.size() + size); 20 | buffer_.insert(buffer_.end(), data, data + size); 21 | return size; 22 | } 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/Transport/BufferIterator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | BufferIterator::BufferIterator(const Buffer& buffer, size_t pPosition) : buffer_(buffer), position_(0) { 10 | seek(pPosition); 11 | } 12 | 13 | size_t BufferIterator::position() const { 14 | return position_; 15 | } 16 | 17 | size_t BufferIterator::remaining() const { 18 | return buffer_.size() - position_; 19 | } 20 | 21 | void BufferIterator::set(const Buffer& buffer) { 22 | buffer_ = buffer; 23 | position_ = 0; 24 | } 25 | 26 | bool BufferIterator::seek(size_t pPosition) { 27 | if (pPosition > buffer_.size()) { 28 | return false; 29 | } 30 | 31 | position_ = pPosition; 32 | return true; 33 | } 34 | 35 | bool BufferIterator::isValid() const { 36 | return remaining() > 0; 37 | } 38 | 39 | Event::Source BufferIterator::eventSource() const { 40 | return Event::Source(); 41 | } 42 | 43 | size_t BufferIterator::read(uint8_t* data, size_t size) { 44 | const size_t readSize = std::min(size, remaining()); 45 | 46 | memcpy(data, &buffer_[position_], readSize); 47 | position_ += readSize; 48 | 49 | return readSize; 50 | } 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/Transport/BufferedStream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace p2p { 10 | 11 | BufferedStream::BufferedStream(IStream& stream, size_t pBufferSize) 12 | : stream_(stream), data_(new uint8_t[pBufferSize]), 13 | bufferSize_(pBufferSize), readPos_(0), writePos_(0) { } 14 | 15 | size_t BufferedStream::read(size_t dataSize) { 16 | // How much data should be read at maximum. 17 | const size_t desiredReadSize = std::max(dataSize, size()) - size(); 18 | 19 | // How much data can be read (due to limited capacity). 20 | const size_t maxReadSize = std::min(capacity(), desiredReadSize); 21 | 22 | // Read any extra data from the stream. 23 | const size_t readSize = stream_.read(data_.get() + writePos_, maxReadSize); 24 | 25 | // Advance the write position. 26 | writePos_ += readSize; 27 | 28 | return size(); 29 | } 30 | 31 | void BufferedStream::consume(size_t consumeSize) { 32 | readPos_ += std::min(consumeSize, size()); 33 | 34 | if (readPos_ == writePos_) { 35 | readPos_ = writePos_ = 0; 36 | } 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/Transport/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-transport STATIC 2 | BinaryStream.cpp 3 | Buffer.cpp 4 | BufferBuilder.cpp 5 | BufferedStream.cpp 6 | BufferIterator.cpp 7 | StringStream.cpp 8 | ) 9 | 10 | -------------------------------------------------------------------------------- /src/Transport/StringStream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace p2p { 10 | 11 | StringIStream::StringIStream(const std::string& sourceString) : string_(sourceString), position_(0) { } 12 | 13 | bool StringIStream::isValid() const { 14 | return string_.size() > position_; 15 | } 16 | 17 | size_t StringIStream::read(uint8_t* data, size_t size) { 18 | const size_t readSize = std::min(size, string_.size() - position_); 19 | 20 | memcpy(data, &(string_.c_str())[position_], readSize); 21 | position_ += readSize; 22 | 23 | return readSize; 24 | } 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/UDP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-udp STATIC Socket.cpp) 2 | -------------------------------------------------------------------------------- /src/Util/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(openp2p-util STATIC 2 | String.cpp 3 | Timer.cpp 4 | ) 5 | 6 | -------------------------------------------------------------------------------- /src/Util/String.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | std::string STR(const char* format, ...) { 9 | va_list varArgList; 10 | 11 | size_t bufferSize = 1024; 12 | char stackBuffer[1024]; 13 | std::vector dynamicBuffer; 14 | char* buffer = &stackBuffer[0]; 15 | 16 | while(true) { 17 | va_start(varArgList, format); 18 | const int needed = vsnprintf(buffer, bufferSize, format, varArgList); 19 | va_end(varArgList); 20 | 21 | // In case the buffer provided is too small, some 22 | // platforms return the needed buffer size, whereas 23 | // some simply return -1. 24 | if(needed <= (int)bufferSize && needed >= 0) { 25 | return std::string(buffer, (size_t) needed); 26 | } 27 | 28 | // Need to increase buffer size; use needed size if available. 29 | bufferSize = (needed > 0) ? (needed + 1) : (bufferSize * 2); 30 | dynamicBuffer.resize(bufferSize); 31 | buffer = &dynamicBuffer[0]; 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/Util/Timer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace p2p { 8 | 9 | Timer::Timer() { } 10 | 11 | double Timer::getTime() { 12 | timeval tv; 13 | gettimeofday(&tv, NULL); 14 | return double(tv.tv_sec) + (double(tv.tv_usec) / 1000000.0); 15 | } 16 | 17 | double Timer::getResolution() { 18 | double startTime = getTime(); 19 | double endTime = startTime; 20 | 21 | while (startTime == endTime) { 22 | endTime = getTime(); 23 | } 24 | 25 | return endTime - startTime; 26 | } 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /tests/BufferTest.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BUFFERTEST_HPP 2 | #define BUFFERTEST_HPP 3 | 4 | #include 5 | #include 6 | #include "Test.hpp" 7 | #include 8 | #include 9 | #include 10 | 11 | class BufferTest: public Test { 12 | public: 13 | inline std::string name() { 14 | return "Buffer Test"; 15 | } 16 | 17 | inline bool run(Output& output) { 18 | using namespace OpenP2P; 19 | { 20 | int64_t a = -4000; 21 | uint32_t b = 42; 22 | uint8_t c = 1; 23 | 24 | Buffer buffer; 25 | BufferBuilder builder(buffer); 26 | BinaryOStream stream(builder); 27 | 28 | if (!(stream << a << b << c)) { 29 | output.error("Failed to build buffer"); 30 | return false; 31 | } 32 | 33 | int64_t d; 34 | uint32_t e; 35 | uint8_t f; 36 | 37 | BufferIterator iterator(buffer); 38 | BinaryIStream readStream(iterator); 39 | readStream >> d >> e >> f; 40 | 41 | if (a != d || b != e || c != f) { 42 | output.error("Data from iterator does not match data from building the buffer"); 43 | return false; 44 | } 45 | 46 | //All data in buffer should have been consumed - so this should fail 47 | uint8_t someData; 48 | 49 | if (readStream >> someData) { 50 | output.error("Iterator gives more data than it should"); 51 | return false; 52 | } 53 | } 54 | return true; 55 | } 56 | 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # TODO: replace with CTest. 2 | # add_executable(tests Test.cpp) 3 | # target_link_libraries(tests openp2p-crypt openp2p-oftorrent openp2p-rootnetwork openp2p-tcp openp2p-udp openp2p boost_thread boost_system ) 4 | -------------------------------------------------------------------------------- /tests/Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Test.hpp" 3 | #include "BufferTest.hpp" 4 | 5 | void Output::warning(const std::string& str) { 6 | std::cout << "WARNING: " << str << std::endl; 7 | } 8 | 9 | void Output::error(const std::string& str) { 10 | std::cout << "ERROR: " << str << std::endl; 11 | } 12 | 13 | int main() { 14 | BufferTest bufferTest; 15 | 16 | std::vector tests_; 17 | tests_.push_back(&bufferTest); 18 | 19 | size_t failures = 0; 20 | Output output; 21 | 22 | std::vector::iterator i; 23 | 24 | for (i = tests_.begin(); i != tests_.end(); ++i) { 25 | std::cout << "---Running test \"" << (*i)->name() << "\"" << std::endl; 26 | bool success = (*i)->run(output); 27 | std::cout << "---Test " << (success ? "Passed" : "Failed") << std::endl; 28 | 29 | if (!success) { 30 | failures++; 31 | } 32 | } 33 | 34 | std::cout << std::endl << "Finished with " << failures << " failure" << (failures == 1 ? "" : "s") << "." << std::endl; 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /tests/Test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_HPP 2 | #define TEST_HPP 3 | 4 | #include 5 | 6 | class Output { 7 | public: 8 | void warning(const std::string& str); 9 | 10 | void error(const std::string& str); 11 | 12 | }; 13 | 14 | class Test { 15 | public: 16 | virtual std::string name() = 0; 17 | 18 | virtual bool run(Output& output) = 0; 19 | 20 | }; 21 | 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory( 2 | FolderSync-FUSE 3 | ) 4 | 5 | add_subdirectory( 6 | RootNetwork 7 | ) 8 | 9 | -------------------------------------------------------------------------------- /tools/FolderSync-FUSE/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 2 | 3 | add_subdirectory(FUSE) 4 | 5 | add_executable(folderSync 6 | FileSystemWrapper.cpp 7 | HandleRef.cpp 8 | NodeSystem.cpp 9 | main.cpp 10 | ) 11 | 12 | target_link_libraries(folderSync 13 | openp2p-foldersync 14 | openp2p-crypt 15 | openp2p-transport 16 | openp2p-event 17 | fusewrapper 18 | fuse 19 | cryptopp 20 | pthread 21 | ) 22 | 23 | -------------------------------------------------------------------------------- /tools/FolderSync-FUSE/FUSE/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_definitions(-D_FILE_OFFSET_BITS=64) 2 | 3 | add_library(fusewrapper 4 | FileSystem.cpp 5 | Path.cpp 6 | ) 7 | 8 | -------------------------------------------------------------------------------- /tools/FolderSync-FUSE/FUSE/ErrorException.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FUSE_ERROREXCEPTION_HPP 2 | #define FUSE_ERROREXCEPTION_HPP 3 | 4 | namespace FUSE { 5 | 6 | /** 7 | * \brief Error Exception. 8 | * 9 | * Instances of this class should be thrown 10 | * to indicate file system errors (using 11 | * values from errno.h); these will be caught 12 | * and returned as errors to FUSE. 13 | */ 14 | class ErrorException { 15 | public: 16 | inline ErrorException(int e) : 17 | error_(e) { } 18 | 19 | inline int error() const { 20 | return error_; 21 | } 22 | 23 | private: 24 | int error_; 25 | 26 | }; 27 | 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /tools/FolderSync-FUSE/FUSE/Handle.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FUSE_HANDLE_HPP 2 | #define FUSE_HANDLE_HPP 3 | 4 | #include 5 | 6 | namespace FUSE { 7 | 8 | typedef uint64_t Handle; 9 | 10 | } 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /tools/FolderSync-FUSE/FUSE/Path.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FUSE_PATH_HPP 2 | #define FUSE_PATH_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace FUSE { 9 | 10 | class Path { 11 | public: 12 | Path(); 13 | Path(const Path&) = default; 14 | Path(Path&& path) noexcept; 15 | Path(const std::string& pathString); 16 | 17 | Path& operator=(Path path); 18 | 19 | bool empty() const; 20 | 21 | size_t size() const; 22 | 23 | const std::string& front() const; 24 | 25 | const std::string& back() const; 26 | 27 | const std::string& at(size_t index) const; 28 | 29 | Path parent() const; 30 | 31 | bool hasChild(const Path& child) const; 32 | 33 | Path rebase(const Path& oldParent, const Path& newParent) const; 34 | 35 | Path subpath(size_t position, size_t length) const; 36 | 37 | std::size_t hash() const; 38 | 39 | std::string toString() const; 40 | 41 | Path operator+(const std::string& component) const; 42 | Path operator+(const Path& path) const; 43 | 44 | bool operator==(const Path&) const; 45 | bool operator!=(const Path&) const; 46 | bool operator<(const Path&) const; 47 | 48 | private: 49 | std::vector components_; 50 | 51 | }; 52 | 53 | } 54 | 55 | namespace std { 56 | 57 | template<> 58 | struct hash { 59 | std::size_t operator()(const FUSE::Path& path) const { 60 | return path.hash(); 61 | } 62 | }; 63 | 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /tools/FolderSync-FUSE/FileSystemWrapper.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENP2P_FOLDERSYNC_FILESYSTEMWRAPPER_HPP 2 | #define OPENP2P_FOLDERSYNC_FILESYSTEMWRAPPER_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace p2p { 14 | 15 | namespace FolderSync { 16 | 17 | class NodeSystem; 18 | 19 | class FileSystemWrapper: public FUSE::FileSystem { 20 | public: 21 | FileSystemWrapper(NodeSystem& nodeSystem); 22 | 23 | FUSE::Handle openFile(const FUSE::Path& path); 24 | 25 | void closeFile(FUSE::Handle handle); 26 | 27 | size_t readFile(FUSE::Handle handle, size_t offset, uint8_t* buffer, size_t size) const; 28 | 29 | size_t writeFile(FUSE::Handle handle, size_t offset, const uint8_t* buffer, size_t size); 30 | 31 | void resize(const FUSE::Path& path, size_t size); 32 | 33 | FUSE::Handle openDirectory(const FUSE::Path& path); 34 | 35 | void closeDirectory(FUSE::Handle handle); 36 | 37 | std::vector readDirectory(FUSE::Handle handle) const; 38 | 39 | FUSE::Handle createAndOpenFile(const FUSE::Path& path, mode_t mode); 40 | 41 | void removeFile(const FUSE::Path& path); 42 | 43 | void createDirectory(const FUSE::Path& path, mode_t mode); 44 | 45 | void removeDirectory(const FUSE::Path& path); 46 | 47 | void rename(const FUSE::Path& sourcePath, const FUSE::Path& destPath); 48 | 49 | struct stat getAttributes(const FUSE::Path& path) const; 50 | 51 | void changeMode(const FUSE::Path& path, mode_t mode); 52 | 53 | void changeOwner(const FUSE::Path& path, uid_t user, gid_t group); 54 | 55 | private: 56 | // Non-copyable. 57 | FileSystemWrapper(const FileSystemWrapper&) = delete; 58 | FileSystemWrapper& operator=(FileSystemWrapper) = delete; 59 | 60 | NodeSystem& nodeSystem_; 61 | 62 | }; 63 | 64 | } 65 | 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /tools/FolderSync-FUSE/HandleRef.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "HandleRef.hpp" 9 | #include "NodeSystem.hpp" 10 | 11 | namespace p2p { 12 | 13 | namespace FolderSync { 14 | 15 | HandleRef::HandleRef() noexcept 16 | : nodeSystem_(nullptr), handle_(0) { } 17 | 18 | HandleRef::HandleRef(NodeSystem& nodeSystem, FUSE::Handle handle) 19 | : nodeSystem_(&nodeSystem), handle_(handle) { 20 | assert(nodeSystem_ != nullptr); 21 | } 22 | 23 | HandleRef::HandleRef(HandleRef&& ref) noexcept 24 | : HandleRef() { 25 | std::swap(nodeSystem_, ref.nodeSystem_); 26 | std::swap(handle_, ref.handle_); 27 | } 28 | 29 | HandleRef::~HandleRef() { 30 | if (nodeSystem_ == nullptr) { 31 | return; 32 | } 33 | 34 | nodeSystem_->closeNode(handle_); 35 | } 36 | 37 | HandleRef& HandleRef::operator=(HandleRef ref) { 38 | std::swap(nodeSystem_, ref.nodeSystem_); 39 | std::swap(handle_, ref.handle_); 40 | return *this; 41 | } 42 | 43 | FUSE::Handle HandleRef::get() const { 44 | assert(nodeSystem_ != nullptr); 45 | return handle_; 46 | } 47 | 48 | FUSE::Handle HandleRef::release() { 49 | assert(nodeSystem_ != nullptr); 50 | nodeSystem_ = nullptr; 51 | return handle_; 52 | } 53 | 54 | HandleRef openPath(NodeSystem& nodeSystem, const FUSE::Path& path) { 55 | auto handle = HandleRef(nodeSystem, nodeSystem.openRoot()); 56 | 57 | for (size_t i = 0; i < path.size(); i++) { 58 | handle = HandleRef(nodeSystem, nodeSystem.openChild(handle.get(), path.at(i))); 59 | } 60 | 61 | return handle; 62 | } 63 | 64 | } 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /tools/FolderSync-FUSE/HandleRef.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENP2P_FOLDERSYNC_HANDLEREF_HPP 2 | #define OPENP2P_FOLDERSYNC_HANDLEREF_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace p2p { 8 | 9 | namespace FolderSync { 10 | 11 | class NodeSystem; 12 | 13 | class HandleRef { 14 | public: 15 | HandleRef() noexcept; 16 | HandleRef(HandleRef&& ref) noexcept; 17 | HandleRef(NodeSystem& nodeSystem, FUSE::Handle handle); 18 | ~HandleRef(); 19 | 20 | HandleRef& operator=(HandleRef ref); 21 | 22 | FUSE::Handle get() const; 23 | 24 | FUSE::Handle release(); 25 | 26 | private: 27 | // Non-copyable. 28 | HandleRef(const HandleRef&) = delete; 29 | 30 | NodeSystem* nodeSystem_; 31 | FUSE::Handle handle_; 32 | 33 | }; 34 | 35 | HandleRef openPath(NodeSystem& nodeSystem, const FUSE::Path& path); 36 | 37 | } 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /tools/FolderSync-FUSE/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "NodeSystem.hpp" 25 | #include "FileSystemWrapper.hpp" 26 | 27 | using namespace p2p; 28 | 29 | int main(int argc, char** argv) { 30 | if (argc != 3) { 31 | printf("Usage: %s [mount point] [block-path]\n", argv[0]); 32 | return 1; 33 | } 34 | 35 | printf("Max file size: %.2f GiB.\n", 36 | double(p2p::FolderSync::NODE_MAX_BYTES) / double(1024 * 1024 * 1024)); 37 | 38 | const std::string mountPoint = argv[1]; 39 | const std::string blockPath = argv[2]; 40 | 41 | //FolderSync::MemDatabase database; 42 | FolderSync::FileDatabase database(blockPath); 43 | FolderSync::NodeSystem nodeSystem(database); 44 | FolderSync::FileSystemWrapper fileSystem(nodeSystem); 45 | 46 | return FUSE::run(mountPoint, fileSystem); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tools/RootNetwork/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(networkGenerator 2 | Logger.cpp 3 | networkGenerator.cpp 4 | ) 5 | 6 | target_link_libraries(networkGenerator 7 | openp2p-rootnetwork 8 | openp2p-udp 9 | openp2p-ip 10 | openp2p-crypt 11 | openp2p-transport 12 | openp2p-concurrency 13 | openp2p-event 14 | openp2p-util 15 | boost_thread 16 | boost_system 17 | cryptopp 18 | pthread 19 | ) 20 | 21 | add_executable(rootNetworkClient 22 | Logger.cpp 23 | rootNetworkClient.cpp 24 | stringtoargcargv.cpp 25 | ) 26 | 27 | target_link_libraries(rootNetworkClient 28 | openp2p-rootnetwork 29 | openp2p-udp 30 | openp2p-ip 31 | openp2p-crypt 32 | openp2p-transport 33 | openp2p-concurrency 34 | openp2p-event 35 | openp2p-util 36 | boost_thread 37 | boost_system 38 | cryptopp 39 | pthread 40 | ) 41 | 42 | -------------------------------------------------------------------------------- /tools/RootNetwork/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "Logger.hpp" 7 | 8 | Logger::Logger() { } 9 | 10 | Logger::~Logger() { 11 | printf("\r"); 12 | fflush(stdout); 13 | } 14 | 15 | void Logger::showPrompt() { 16 | printf("\r$ "); 17 | fflush(stdout); 18 | } 19 | 20 | void Logger::log(const std::string& message) { 21 | std::lock_guard lock(mutex_); 22 | printf("\r%s\n", message.c_str()); 23 | printf("$ "); 24 | fflush(stdout); 25 | } 26 | 27 | std::string readLine() { 28 | std::string line; 29 | 30 | while (true) { 31 | const int c = getc(stdin); 32 | if (c == EOF) { 33 | return ""; 34 | } 35 | 36 | if (c == '\n') { 37 | if (!line.empty()) { 38 | break; 39 | } else { 40 | continue; 41 | } 42 | } 43 | 44 | line += (char) c; 45 | } 46 | 47 | return line; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /tools/RootNetwork/Logger.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LOGGER_H 2 | #define LOGGER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | class Logger { 10 | public: 11 | Logger(); 12 | ~Logger(); 13 | 14 | void showPrompt(); 15 | 16 | void log(const std::string& message); 17 | 18 | private: 19 | std::mutex mutex_; 20 | 21 | }; 22 | 23 | std::string readLine(); 24 | 25 | #endif 26 | --------------------------------------------------------------------------------