├── .gitattributes ├── src ├── lib │ ├── README.md │ ├── exception │ │ ├── Error.cpp │ │ ├── Exception.cpp │ │ └── Instances.cpp │ ├── utility │ │ ├── Stream.cpp │ │ └── Stream_buf.cpp │ ├── sha256.cpp │ ├── Mongoose.cpp │ ├── RestServ.cpp │ └── logging.cpp ├── README.md ├── node.cpp ├── CMakeLists.txt ├── blockchain.cpp ├── main.cpp ├── network.cpp ├── commands.cpp ├── consensus.cpp ├── tinychain.cpp └── database.cpp ├── include ├── metaverse │ ├── mgbubble │ │ ├── ReadME.md │ │ ├── compat │ │ │ ├── define.hpp │ │ │ └── string_view.h │ │ ├── utility │ │ │ ├── Queue.hpp │ │ │ ├── Tokeniser.hpp │ │ │ ├── Compare.hpp │ │ │ ├── Stream_buf.hpp │ │ │ ├── Stream.hpp │ │ │ └── String.hpp │ │ ├── exception │ │ │ ├── Error.hpp │ │ │ ├── Exception.hpp │ │ │ └── Instances.hpp │ │ ├── RestServ.hpp │ │ ├── MongooseCli.hpp │ │ └── Mongoose.hpp │ └── mgbubble.hpp ├── mgbubble.hpp ├── README.md ├── tinychain │ ├── network.hpp │ ├── commands.hpp │ ├── consensus.hpp │ ├── node.hpp │ ├── sha256.hpp │ ├── database.hpp │ ├── blockchain.hpp │ ├── logging.hpp │ └── tinychain.hpp └── sqlite3pp │ ├── sqlite3ppext.ipp │ ├── sqlite3ppext.h │ ├── sqlite3pp.h │ └── sqlite3pp.ipp ├── etc ├── CMakeLists.txt ├── README.md └── index.html ├── contrib ├── CMakeLists.txt ├── README.md ├── sqlite │ └── CMakeLists.txt ├── jsoncpp │ ├── CMakeLists.txt │ └── json │ │ └── json-forwards.h └── mongoose │ └── CMakeLists.txt ├── test └── README.md ├── cli-tinychain ├── README.md ├── CMakeLists.txt └── main.cpp ├── .gitignore ├── README.md └── CMakeLists.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | *.c linguist-language=c++ 2 | -------------------------------------------------------------------------------- /src/lib/README.md: -------------------------------------------------------------------------------- 1 | MODULES 2 | -------------- 3 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/ReadME.md: -------------------------------------------------------------------------------- 1 | "mgbubble" is mongoose wrapper in c++14 for MVS http service 2 | -------------------------------------------------------------------------------- /etc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(etc_FILES 2 | index.html 3 | ) 4 | 5 | INSTALL(FILES ${etc_FILES} DESTINATION bin) 6 | -------------------------------------------------------------------------------- /contrib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_SUBDIRECTORY(mongoose) 2 | ADD_SUBDIRECTORY(jsoncpp) 3 | IF(WIN32) 4 | ADD_SUBDIRECTORY(sqlite) 5 | ENDIF() -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # tinychain 2 | A mini blockchain implementation in C++14 构建迷你区块链——《深入浅出区块链》 3 | 4 | ## 说明 INTRODUNCTION 5 | 单元测试代码(未开始) 6 | -------------------------------------------------------------------------------- /cli-tinychain/README.md: -------------------------------------------------------------------------------- 1 | # tinychain 2 | A mini blockchain implementation in C++14 构建迷你区块链——《深入浅出区块链》 3 | 4 | ## 说明 INTRODUNCTION 5 | 命令行工具,使用户可以在终端发起命令 6 | -------------------------------------------------------------------------------- /etc/README.md: -------------------------------------------------------------------------------- 1 | # tinychain 2 | A mini blockchain implementation in C++14 构建迷你区块链——《深入浅出区块链》 3 | 4 | ## 说明 INTRODUNCTION 5 | index.html - 一个websocket可视化前端,提供可监控的区块和交易观察入口(未完成) 6 | -------------------------------------------------------------------------------- /include/mgbubble.hpp: -------------------------------------------------------------------------------- 1 | //"mgbubble" is mongoose wrapper in c++14 for MVS http service 2 | 3 | #include 4 | #include 5 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble.hpp: -------------------------------------------------------------------------------- 1 | //"mgbubble" is mongoose wrapper in c++14 for MVS http service 2 | 3 | #include 4 | #include 5 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | # tinychain 2 | A mini blockchain implementation in C++14 构建迷你区块链——《深入浅出区块链》 3 | 4 | ## 说明 INTRODUNCTION 5 | lib - 包含元界移植过来的代码和其他开源源码,提供HTTPServer,SHA256等其他基础组件 6 | 7 | 当前目录的cpp源码 - tinychain核心源码,每个文件头会有注释 8 | -------------------------------------------------------------------------------- /src/node.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #include 7 | #include 8 | 9 | namespace tinychain 10 | { 11 | 12 | 13 | void node::test(){} 14 | 15 | 16 | } //tinychain 17 | 18 | -------------------------------------------------------------------------------- /contrib/README.md: -------------------------------------------------------------------------------- 1 | # tinychain 2 | A mini blockchain implementation in C++14 构建迷你区块链——《深入浅出区块链》 3 | 4 | ## 说明 INTRODUNCTION 5 | json - 废弃版本 6 | 7 | jsoncpp - 通过源代码集成的jsoncpp 8 | 9 | mongoose - 通过源代码集成的开源微型嵌入式HTTP Server 10 | 11 | sqlite - sqlite3官方接口 12 | -------------------------------------------------------------------------------- /include/README.md: -------------------------------------------------------------------------------- 1 | # tinychain 2 | A mini blockchain implementation in C++14 构建迷你区块链——《深入浅出区块链》 3 | 4 | ## 说明 INTRODUNCTION 5 | metaverse - 从元界移植过来的代码,提供HTTP Wrapper 6 | 7 | mgbubble.hpp - 元界部分的头文件包含 8 | 9 | sqlite3pp - 一个sqlite3的第三方C++11 wrapper 10 | 11 | tinychain - 核心代码 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | touch.sh 3 | # Compiled Object files 4 | *.slo 5 | *.lo 6 | *.o 7 | *.obj 8 | 9 | # Precompiled Headers 10 | *.gch 11 | *.pch 12 | 13 | # Compiled Dynamic libraries 14 | *.so 15 | *.dylib 16 | *.dll 17 | 18 | # Fortran module files 19 | *.mod 20 | *.smod 21 | 22 | # Compiled Static libraries 23 | *.lai 24 | *.la 25 | *.a 26 | *.lib 27 | 28 | # Executables 29 | *.exe 30 | *.out 31 | *.app 32 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FILE(GLOB_RECURSE tinychain_SOURCES "*.cpp") 2 | 3 | ADD_EXECUTABLE(tinychain ${tinychain_SOURCES}) 4 | 5 | IF(WIN32) 6 | TARGET_LINK_LIBRARIES(tinychain ${Boost_LIBRARIES} ${jsoncpp_LIBRARY} ${mongoose_LIBRARY} ${sqlite_LIBRARY}) 7 | ELSEIF(ENABLE_SHARED_LIBS) 8 | TARGET_LINK_LIBRARIES(tinychain ${Boost_LIBRARIES} ${jsoncpp_LIBRARY} ${mongoose_LIBRARY} sqlite3 cryptopp) 9 | ELSE() 10 | TARGET_LINK_LIBRARIES(tinychain ${Boost_LIBRARIES} ${jsoncpp_LIBRARY} ${mongoose_LIBRARY} sqlite3 cryptopp dl) 11 | ENDIF() 12 | 13 | INSTALL(TARGETS tinychain DESTINATION bin) 14 | 15 | -------------------------------------------------------------------------------- /cli-tinychain/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | FILE(GLOB_RECURSE cli-tinychain_SOURCES "*.cpp") 3 | 4 | ADD_DEFINITIONS(-DBCX_STATIC=1) 5 | 6 | ADD_EXECUTABLE(cli-tinychain ${cli-tinychain_SOURCES}) 7 | 8 | IF(NOT WIN32) 9 | # for experimental/string_view 10 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations") 11 | ENDIF() 12 | 13 | IF(ENABLE_SHARED_LIBS) 14 | TARGET_LINK_LIBRARIES(cli-tinychain ${mongoose_LIBRARY} ${jsoncpp_LIBRARY}) 15 | ELSE() 16 | TARGET_LINK_LIBRARIES(cli-tinychain ${mongoose_LIBRARY} ${jsoncpp_LIBRARY}) 17 | ENDIF() 18 | 19 | INSTALL(TARGETS cli-tinychain DESTINATION bin) 20 | -------------------------------------------------------------------------------- /contrib/sqlite/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FILE(GLOB_RECURSE sqlite_SOURCES "*.c") 2 | 3 | ADD_LIBRARY(sqlite_static STATIC ${sqlite_SOURCES}) 4 | SET_TARGET_PROPERTIES(sqlite_static PROPERTIES OUTPUT_NAME sqlite) 5 | TARGET_LINK_LIBRARIES(sqlite_static) 6 | INSTALL(TARGETS sqlite_static DESTINATION lib) 7 | 8 | IF(ENABLE_SHARED_LIBS) 9 | ADD_LIBRARY(sqlite_shared SHARED ${sqlite_SOURCES}) 10 | SET_TARGET_PROPERTIES(sqlite_shared PROPERTIES OUTPUT_NAME sqlite) 11 | TARGET_LINK_LIBRARIES(sqlite_shared) 12 | INSTALL(TARGETS sqlite_shared DESTINATION lib) 13 | ENDIF() 14 | -------------------------------------------------------------------------------- /include/tinychain/network.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #pragma once 7 | #include 8 | 9 | namespace tinychain 10 | { 11 | 12 | void ws_send(std::string&& msg); 13 | 14 | class network 15 | { 16 | public: 17 | network() noexcept = default; 18 | network(const network&) noexcept = default; 19 | network(network&&) noexcept = default; 20 | network& operator=(network&&) noexcept = default; 21 | network& operator=(const network&) noexcept = default; 22 | 23 | void print(){ std::cout<<"class network"< 8 | #include 9 | #include 10 | 11 | namespace tinychain 12 | { 13 | 14 | class commands 15 | { 16 | public: 17 | typedef std::vector vargv_t; 18 | commands(const vargv_t& vargv, node& node):vargv_(vargv), node_(node) { 19 | } 20 | 21 | commands(const commands&) = default; 22 | commands(commands&&) = default; 23 | commands& operator=(commands&&) = default; 24 | commands& operator=(const commands&) = default; 25 | 26 | bool exec(Json::Value& out); 27 | 28 | static const vargv_t commands_list; 29 | 30 | private: 31 | const vargv_t& vargv_; 32 | node& node_; 33 | }; 34 | 35 | 36 | 37 | }// tinychain 38 | -------------------------------------------------------------------------------- /src/blockchain.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #include 7 | #include 8 | 9 | namespace tinychain 10 | { 11 | 12 | void blockchain::test(){} 13 | 14 | block blockchain::get_last_block() { 15 | return chain_.get_last_block(); 16 | } 17 | 18 | bool blockchain::get_block(sha256_t block_hash, block& b) { 19 | if (!chain_.get_block(block_hash, b)) { 20 | return false; 21 | } 22 | return true; 23 | } 24 | 25 | uint64_t blockchain::get_height(){ 26 | return chain_.height(); 27 | } 28 | 29 | bool blockchain::get_balance(address_t address, uint64_t balance){ 30 | return true; 31 | } 32 | 33 | bool blockchain::get_tx(sha256_t tx_hash, tx& t) { 34 | if (!chain_.get_tx(tx_hash, t)) { 35 | return false; 36 | } 37 | return true; 38 | } 39 | 40 | } //tinychain 41 | 42 | -------------------------------------------------------------------------------- /include/tinychain/consensus.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #pragma once 7 | #include 8 | #include 9 | 10 | namespace tinychain 11 | { 12 | 13 | class miner 14 | { 15 | public: 16 | miner(blockchain& chain):chain_(chain) {}; 17 | miner(const miner&) = default; 18 | miner(miner&&) = default; 19 | miner& operator=(miner&&) = default; 20 | miner& operator=(const miner&) = default; 21 | 22 | void print(){ std::cout<<"class miner"< 17 | 18 | namespace mgbubble { 19 | 20 | 21 | } // mgbubble 22 | -------------------------------------------------------------------------------- /contrib/mongoose/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FILE(GLOB_RECURSE mongoose_SOURCES "*.c") 2 | #aux_source_directory(${CMAKE_CURRENT_LIST_DIR}) 3 | #SET(mongoose_SOURCES ${CMAKE_CURRENT_LIST_DIR}) 4 | 5 | # Mongoose does not compile with strict aliasing. 6 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing") 7 | IF(MG_ENABLE_DEBUG) 8 | ADD_DEFINITIONS(-DMG_ENABLE_DEBUG) 9 | ELSE() 10 | ADD_DEFINITIONS(-DMG_DISABLE_STDIO) 11 | ENDIF() 12 | 13 | ADD_LIBRARY(mongoose_static STATIC ${mongoose_SOURCES}) 14 | SET_TARGET_PROPERTIES(mongoose_static PROPERTIES OUTPUT_NAME mongoose) 15 | TARGET_LINK_LIBRARIES(mongoose_static) 16 | INSTALL(TARGETS mongoose_static DESTINATION lib) 17 | 18 | IF(ENABLE_SHARED_LIBS) 19 | ADD_LIBRARY(mongoose_shared SHARED ${mongoose_SOURCES}) 20 | SET_TARGET_PROPERTIES(mongoose_shared PROPERTIES OUTPUT_NAME mongoose) 21 | TARGET_LINK_LIBRARIES(mongoose_shared) 22 | INSTALL(TARGETS mongoose_shared DESTINATION lib) 23 | ENDIF() 24 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/compat/define.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS) - Metaverse. 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under the terms of the 5 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 6 | * License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License along with this program; if 13 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 14 | * 02110-1301, USA. 15 | */ 16 | #ifndef MVS_ASH_DEFS_HPP 17 | #define MVS_ASH_DEFS_HPP 18 | 19 | /** 20 | * @addtogroup Util 21 | * @{ 22 | */ 23 | 24 | /** 25 | * Macro for exporting classes and functions that compose the public API. 26 | */ 27 | #ifdef _WIN32 28 | #define MVS_API 29 | #else 30 | #define MVS_API __attribute__((visibility("default"))) 31 | #endif 32 | 33 | #define LOG_HTTP "http" 34 | 35 | /** @} */ 36 | 37 | #endif // MVS_ASH_DEFS_HPP 38 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/compat/string_view.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS) 3 | * 4 | * This file is part of metaverse. 5 | * 6 | * metaverse is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License with 8 | * additional permissions to the one published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) 10 | * any later version. For more information see LICENSE. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef MVS___STRING_VIEW__ 21 | #define MVS___STRING_VIEW__ 22 | 23 | #ifdef _WIN32 24 | #include 25 | #include 26 | #define string_view boost::string_view 27 | 28 | #else 29 | 30 | #include 31 | #define string_view std::experimental::string_view 32 | 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/tinychain/node.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #pragma once 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace tinychain 15 | { 16 | 17 | class node 18 | { 19 | public: 20 | node() noexcept { 21 | log::info("node")<<"node started"; 22 | } 23 | 24 | node(const node&) = default; 25 | node(node&&) = default; 26 | node& operator=(node&&) = default; 27 | node& operator=(const node&) = default; 28 | 29 | void test(); 30 | bool check(); 31 | 32 | void miner_run(address_t address) { 33 | // miner 34 | address_t miner_addr; 35 | if (address.empty()){ 36 | miner_addr = blockchain_.get_new_key_pair().address(); 37 | } else { 38 | miner_addr = address; 39 | } 40 | std::thread miner_service(std::bind(&miner::start, &miner_, miner_addr)); 41 | miner_service.detach(); 42 | } 43 | 44 | blockchain& chain() { return blockchain_; } 45 | network& p2p() { return network_; } 46 | 47 | private: 48 | 49 | network network_; 50 | blockchain blockchain_; 51 | miner miner_{blockchain_}; 52 | }; 53 | 54 | 55 | 56 | }// tinychain 57 | -------------------------------------------------------------------------------- /src/lib/utility/Stream.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS). 3 | * Copyright (C) 2013, 2016 Swirly Cloud Limited. 4 | * 5 | * This program is free software; you can redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 10 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program; if 14 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | #include 19 | 20 | 21 | using namespace std; 22 | 23 | namespace mgbubble { 24 | 25 | MVS_API void reset(ostream& os) noexcept 26 | { 27 | os.clear(); 28 | os.fill(os.widen(' ')); 29 | os.flags(ios_base::skipws | ios_base::dec); 30 | os.precision(6); 31 | os.width(0); 32 | }; 33 | 34 | OStreamJoiner::~OStreamJoiner() noexcept = default; 35 | 36 | } // mgbubble 37 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/utility/Queue.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | class Queue 8 | { 9 | public: 10 | Queue() = default; 11 | Queue(Queue&&) = default; 12 | 13 | void push(T&& item){ 14 | std::unique_lock lock(lock_); 15 | queue_.push_back(item); 16 | cond_.notify_one(); 17 | } 18 | 19 | void push(const T& item){ 20 | std::unique_lock lock(lock_); 21 | queue_.push_back(item); 22 | cond_.notify_one(); 23 | } 24 | 25 | bool empty(){ 26 | std::unique_lock lock(lock_); 27 | return queue_.empty(); 28 | } 29 | 30 | size_t count(){ 31 | std::unique_lock lock(lock_); 32 | return queue_.size(); 33 | } 34 | 35 | void clear(){ 36 | std::unique_lock lock(lock_); 37 | std::deque tmp; 38 | queue_.swap(tmp); 39 | } 40 | 41 | bool pop(T& front){ 42 | std::unique_lock lock(lock_); 43 | if (!queue_.empty()){ 44 | front = queue_.front(); 45 | queue_.pop_front(); 46 | return true; 47 | } 48 | return false; 49 | } 50 | 51 | bool pop_wait(T& front){ 52 | std::unique_lock lock(lock_); 53 | if (queue_.empty()){ 54 | cond_.wait(lock); 55 | } 56 | if (!queue_.empty()){ 57 | front = queue_.front(); 58 | queue_.pop_front(); 59 | return true; 60 | } 61 | return false; 62 | } 63 | 64 | protected: 65 | mutable std::mutex lock_; 66 | std::condition_variable cond_; 67 | std::deque queue_; 68 | }; 69 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/exception/Error.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS) - Metaverse. 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under the terms of the 5 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 6 | * License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License along with this program; if 13 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 14 | * 02110-1301, USA. 15 | */ 16 | #ifndef MVSD_EXCEPTION_HPP 17 | #define MVSD_EXCEPTION_HPP 18 | 19 | #include 20 | 21 | /** 22 | * @addtogroup App 23 | * @{ 24 | */ 25 | 26 | namespace mgbubble { 27 | 28 | class Error : public Exception { 29 | public: 30 | explicit Error(string_view what) noexcept : Exception{what} {} 31 | ~Error() noexcept = default; 32 | 33 | // Copy. 34 | Error(const Error&) noexcept = default; 35 | Error& operator=(const Error&) noexcept = default; 36 | 37 | // Move. 38 | Error(Error&&) noexcept = default; 39 | Error& operator=(Error&&) noexcept = default; 40 | }; 41 | 42 | } // http 43 | 44 | /** @} */ 45 | 46 | #endif // MVSD_EXCEPTION_HPP 47 | -------------------------------------------------------------------------------- /src/lib/exception/Exception.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS). 3 | * Copyright (C) 2013, 2016 Swirly Cloud Limited. 4 | * 5 | * This program is free software; you can redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 10 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program; if 14 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | #include 18 | 19 | using namespace std; 20 | 21 | namespace mgbubble { 22 | 23 | namespace { 24 | thread_local ErrMsg errMsg_; 25 | } // anonymous 26 | 27 | Exception::Exception(string_view what) noexcept 28 | { 29 | const auto len = min(ErrMsgMax, what.size()); 30 | if (len > 0) { 31 | memcpy(what_, what.data(), len); 32 | } 33 | what_[len] = '\0'; 34 | } 35 | 36 | Exception::~Exception() noexcept = default; 37 | 38 | const char* Exception::what() const noexcept 39 | { 40 | return what_; 41 | } 42 | 43 | ErrMsg& errMsg() noexcept 44 | { 45 | errMsg_.reset(); 46 | return errMsg_; 47 | } 48 | 49 | } // mgbubble 50 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace tinychain; 11 | using namespace mgbubble; 12 | 13 | // global logger 14 | Logger logger; 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | 19 | // 初始化本地数据库 20 | database d; 21 | d.init(); 22 | d.print(); 23 | 24 | // 初始化本地服务 25 | node my_node; 26 | mgbubble::RestServ Server{"webroot", my_node}; 27 | auto& conn = Server.bind("0.0.0.0:8000"); 28 | mg_set_protocol_http_websocket(&conn); 29 | mg_set_timer(&conn, mg_time() + mgbubble::RestServ::session_check_interval); 30 | 31 | // 启动本地服务 32 | log::info("main")<<"httpserver started"; 33 | Server.run(); 34 | 35 | 36 | #if 0 //测试用代码 后续会移除 37 | //std::string input = "grape"; 38 | //auto&& output1 = sha256(input); 39 | //log::info("main") << "sha256('"<< input << "'):" << output1; 40 | 41 | tx tx1("tx1_address", 100); 42 | tx tx2("tx2_address", 200); 43 | 44 | tx tx3("tx3_address", 300); 45 | tx tx4("tx4_address", 400); 46 | 47 | blockchain::memory_pool_t p; 48 | p.push_back(tx1); 49 | p.push_back(tx2); 50 | 51 | block block1(1); 52 | block1.setup(p); 53 | 54 | p.push_back(tx3); 55 | block block2(2); 56 | block2.setup(p); 57 | 58 | block block3(3); 59 | blockchain blockchain1; 60 | blockchain1.push_block(block1); 61 | blockchain1.push_block(block2); 62 | blockchain1.push_block(block3); 63 | blockchain1.print(); 64 | #endif 65 | 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tinychain 2 | A mini blockchain implementation in C++14 构建迷你区块链——《深入浅出区块链》 3 | 4 | ## 简要说明 INTRODUNCTION 5 | tinychain是一个业余的项目,旨在为大家提供微型的简单易懂的供学习的代码。 6 | 以下是涉及的一些基础技术: 7 | * 加密库 - RSA 8 | * 本地持久化存储 - sqlite3 9 | * P2P网络 - 暂定gossip 10 | * 网络文本协议 - JSON-RPC 11 | * HTTP Server - mongoose 12 | * 正在选取中... 13 | 14 | ## 锻造工具 Toolchain 15 | * gcc/clang support C++14 16 | * boost 1.56+ (datetime) 17 | * cmake 18 | * git 19 | * sqlite3 (apt-get install libsqlite3-dev / brew install sqlite3) 20 | * cryptopp (apt-get install libcryptopp-dev / brew install cryptopp) 21 | 22 | ## 构建 Build 23 | On workpath of tinychain: 24 | ``` 25 | $ mkdir -p build && cd build 26 | $ cmake .. 27 | $ make 28 | ``` 29 | 30 | Specifically, build on Windows (example): 31 | ``` 32 | > mkdir build 33 | > cd build 34 | > cmake .. -G "Visual Studio 15 2017 Win64" -DBOOST_ROOT=/local/boost_1_67_0 35 | ``` 36 | Open tinychain.sln under build subfolder with Visual Studio to compile. 37 | 38 | ## 运行 Run 39 | On workpath of tinychain: 40 | ``` 41 | $ cd build/bin 42 | $ mkdir -p webroot && cp -f ../../etc/index.html webroot 43 | $ ./tinychain 44 | ``` 45 | 46 | Specifically, run on Windows (example): 47 | ``` 48 | > cd build\bin\Release 49 | > mkdir webroot 50 | > copy /Y ..\..\..\etc\index.html webroot 51 | > tinychain.exe 52 | ``` 53 | 54 | ## 开发路径 TODO-LIST 55 | 1. 基础代码 - (DONE, to be improved) 56 | 1. PoW 挖矿代码 - (DONE, to be improved) 57 | 1. 加密与账户模型 (DOING) 58 | 1. P2P网络- (TODO) 59 | 1. 命令行与Web动态演示 - (DOING) 60 | 1. 共识可替换为PoS/DPoS/PBFT etc - (TODO) 61 | 62 | ## 仓库介绍 Source code view 63 | * cli-tinychain文件夹:命令行 64 | * contrib文件夹:json与mongoose工具 65 | * etc文件夹:tinychain演示网页等 66 | * include文件夹:tinychain中类的设计以及第三方库的头文件 67 | * src文件夹:tinychain和第三方库的具体实现 68 | -------------------------------------------------------------------------------- /src/network.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #include 7 | #include 8 | #include 9 | 10 | namespace tinychain 11 | { 12 | //using namespace mgbubble; 13 | // 14 | static std::string string_msg; 15 | 16 | static int s_done = 0; 17 | static int s_is_connected = 0; 18 | 19 | void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { 20 | struct websocket_message *wm = (struct websocket_message *) ev_data; 21 | (void) nc; 22 | 23 | switch (ev) { 24 | case MG_EV_CONNECT: { 25 | int status = *((int *) ev_data); 26 | if (status != 0) { 27 | printf("-- Connection error: %d\n", status); 28 | } 29 | break; 30 | } 31 | case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { 32 | printf("-- Connected\n"); 33 | s_is_connected = 1; 34 | break; 35 | } 36 | case MG_EV_POLL: { 37 | log::info("chenhao") << string_msg; 38 | mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, string_msg.c_str(), string_msg.size()); 39 | string_msg = ""; 40 | break; 41 | } 42 | case MG_EV_WEBSOCKET_FRAME: { 43 | printf("%.*s\n", (int) wm->size, wm->data); 44 | break; 45 | } 46 | case MG_EV_CLOSE: { 47 | if (s_is_connected) printf("-- Disconnected\n"); 48 | s_done = 1; 49 | break; 50 | } 51 | } 52 | } 53 | 54 | 55 | void ws_send(std::string&& msg) { 56 | struct mg_mgr mgr; 57 | struct mg_connection *nc; 58 | const char *chat_server_url = "ws://127.0.0.1:8000"; 59 | 60 | mg_mgr_init(&mgr, NULL); 61 | 62 | string_msg = msg; 63 | nc = mg_connect_ws(&mgr, ev_handler, chat_server_url, msg.c_str(), NULL); 64 | if (nc == nullptr) { 65 | log::error("network")<<"Invalid address"; 66 | return; 67 | } 68 | 69 | while (!s_done) { 70 | mg_mgr_poll(&mgr, 100); 71 | } 72 | mg_mgr_free(&mgr); 73 | 74 | } 75 | 76 | 77 | } //tinychain 78 | 79 | -------------------------------------------------------------------------------- /include/tinychain/sha256.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #pragma once 7 | #include 8 | 9 | namespace tinychain 10 | { 11 | 12 | class SHA256 13 | { 14 | protected: 15 | typedef unsigned char uint8; 16 | typedef unsigned int uint32; 17 | typedef unsigned long long uint64; 18 | 19 | const static uint32 sha256_k[]; 20 | static const unsigned int SHA224_256_BLOCK_SIZE = (512/8); 21 | public: 22 | void init(); 23 | void update(const unsigned char *message, unsigned int len); 24 | void final(unsigned char *digest); 25 | static const unsigned int DIGEST_SIZE = ( 256 / 8); 26 | 27 | protected: 28 | void transform(const unsigned char *message, unsigned int block_nb); 29 | unsigned int m_tot_len; 30 | unsigned int m_len; 31 | unsigned char m_block[2*SHA224_256_BLOCK_SIZE]; 32 | uint32 m_h[8]; 33 | }; 34 | 35 | std::string sha256(const std::string& input); 36 | 37 | #define SHA2_SHFR(x, n) (x >> n) 38 | #define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) 39 | #define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n))) 40 | #define SHA2_CH(x, y, z) ((x & y) ^ (~x & z)) 41 | #define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) 42 | #define SHA256_F1(x) (SHA2_ROTR(x, 2) ^ SHA2_ROTR(x, 13) ^ SHA2_ROTR(x, 22)) 43 | #define SHA256_F2(x) (SHA2_ROTR(x, 6) ^ SHA2_ROTR(x, 11) ^ SHA2_ROTR(x, 25)) 44 | #define SHA256_F3(x) (SHA2_ROTR(x, 7) ^ SHA2_ROTR(x, 18) ^ SHA2_SHFR(x, 3)) 45 | #define SHA256_F4(x) (SHA2_ROTR(x, 17) ^ SHA2_ROTR(x, 19) ^ SHA2_SHFR(x, 10)) 46 | #define SHA2_UNPACK32(x, str) \ 47 | { \ 48 | *((str) + 3) = (uint8) ((x) ); \ 49 | *((str) + 2) = (uint8) ((x) >> 8); \ 50 | *((str) + 1) = (uint8) ((x) >> 16); \ 51 | *((str) + 0) = (uint8) ((x) >> 24); \ 52 | } 53 | #define SHA2_PACK32(str, x) \ 54 | { \ 55 | *(x) = ((uint32) *((str) + 3) ) \ 56 | | ((uint32) *((str) + 2) << 8) \ 57 | | ((uint32) *((str) + 1) << 16) \ 58 | | ((uint32) *((str) + 0) << 24); \ 59 | } 60 | 61 | }// tinychain 62 | 63 | -------------------------------------------------------------------------------- /src/commands.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #include 7 | #include 8 | 9 | namespace tinychain 10 | { 11 | 12 | 13 | bool commands::exec(Json::Value& out){ 14 | try { 15 | if (*(vargv_.begin()) == "getnewkey") { 16 | auto&& key = node_.chain().get_new_key_pair(); 17 | out = key.to_json(); 18 | } else if (*(vargv_.begin()) == "listkeys") { 19 | out = node_.chain().list_keys(); 20 | } else if (*(vargv_.begin()) == "send") { 21 | if (vargv_.size() >= 3) { 22 | uint64_t amount = std::stoul(vargv_[2]); 23 | auto ret = node_.chain().send(vargv_[1], amount); 24 | out = ret.toStyledString(); 25 | } else { 26 | out = "Invalid or Empty paramas"; 27 | } 28 | 29 | } else if (*(vargv_.begin()) == "getbalance") { 30 | out = "getbalance-TODO"; 31 | 32 | } else if (*(vargv_.begin()) == "getlastblock") { 33 | auto&& b = node_.chain().get_last_block(); 34 | out = b.to_json(); 35 | 36 | } else if (*(vargv_.begin()) == "getheight") { 37 | out = node_.chain().get_height(); 38 | 39 | } else if (*(vargv_.begin()) == "startmining") { 40 | std::string addr; 41 | if (vargv_.size() >= 2) { 42 | addr = vargv_[1]; 43 | node_.miner_run(addr); 44 | out["result"] = "start mining on address: " + addr; 45 | } else { 46 | node_.miner_run(addr); 47 | out["result"] = "start mining on a random address of your wallet"; 48 | } 49 | } else { 50 | out = " "; 51 | return false; 52 | } 53 | } catch (std::exception& ex) { 54 | log::error("commands")<<"error:"<< ex.what(); 55 | return false; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | const commands::vargv_t command_list = {"getnewkey","getlastblock","getheight","send","getbalance", "startmining"}; 62 | 63 | 64 | } //tinychain 65 | 66 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/utility/Tokeniser.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS) - Metaverse. 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under the terms of the 5 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 6 | * License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License along with this program; if 13 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 14 | * 02110-1301, USA. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | #include 22 | 23 | /** 24 | * @addtogroup Util 25 | * @{ 26 | */ 27 | 28 | namespace mgbubble { 29 | 30 | template 31 | class Tokeniser { 32 | public: 33 | explicit Tokeniser(string_view buf) noexcept { reset(buf); } 34 | explicit Tokeniser() noexcept { reset(""); } 35 | ~Tokeniser() noexcept = default; 36 | 37 | // Copy. 38 | Tokeniser(const Tokeniser& rhs) noexcept = default; 39 | Tokeniser& operator=(const Tokeniser& rhs) noexcept = default; 40 | 41 | // Move. 42 | Tokeniser(Tokeniser&&) noexcept = default; 43 | Tokeniser& operator=(Tokeniser&&) noexcept = default; 44 | 45 | string_view top() const noexcept { return buf_.substr(i_ - buf_.cbegin(), j_ - i_); } 46 | bool empty() const noexcept { return i_ == buf_.cend(); } 47 | void reset(string_view buf) noexcept 48 | { 49 | buf_ = buf; 50 | i_ = buf_.cbegin(); 51 | j_ = std::find(i_, buf_.cend(), DelimN); 52 | } 53 | void pop() noexcept 54 | { 55 | if (j_ != buf_.cend()) { 56 | i_ = j_ + 1; 57 | j_ = std::find(i_, buf_.cend(), DelimN); 58 | } else { 59 | i_ = j_; 60 | } 61 | } 62 | 63 | private: 64 | string_view buf_; 65 | string_view::const_iterator i_, j_; 66 | }; 67 | 68 | } // http 69 | 70 | /** @} */ 71 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/exception/Exception.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS). 3 | * Copyright (C) 2013, 2016 Swirly Cloud Limited. 4 | * 5 | * This program is free software; you can redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 10 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program; if 14 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include // strcpy() 21 | #include 22 | #include 23 | 24 | 25 | namespace mgbubble { 26 | 27 | /** 28 | * Maximum error message length. 29 | */ 30 | constexpr std::size_t ErrMsgMax{127}; 31 | 32 | using ErrMsg = StringBuilder; 33 | 34 | class MVS_API Exception : public std::exception { 35 | public: 36 | explicit Exception(string_view what) noexcept; 37 | 38 | ~Exception() noexcept override; 39 | 40 | // Copy. 41 | Exception(const Exception& rhs) noexcept { *this = rhs; } 42 | Exception& operator=(const Exception& rhs) noexcept 43 | { 44 | std::strcpy(what_, rhs.what_); 45 | return *this; 46 | } 47 | 48 | // Move. 49 | Exception(Exception&&) noexcept = default; 50 | Exception& operator=(Exception&&) noexcept = default; 51 | 52 | const char* what() const noexcept override; 53 | 54 | private: 55 | char what_[ErrMsgMax + 1]; 56 | }; 57 | 58 | /** 59 | * Thread-local error message. This thread-local instance of StringBuilder can be used to format 60 | * error messages before throwing. Note that the StringBuilder is reset each time this function is 61 | * called. 62 | */ 63 | MVS_API ErrMsg& errMsg() noexcept; 64 | 65 | } // mgbubble 66 | 67 | 68 | -------------------------------------------------------------------------------- /cli-tinychain/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS) 3 | * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS) 4 | * 5 | * This file is part of metaverse-explorer. 6 | * 7 | * metaverse-explorer is free software: you can redistribute it and/or 8 | * modify it under the terms of the GNU Affero General Public License with 9 | * additional permissions to the one published by the Free Software 10 | * Foundation, either version 3 of the License, or (at your option) 11 | * any later version. For more information see LICENSE. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | /** 26 | * Invoke this program with the raw arguments provided on the command line. 27 | * All console input and output streams for the application originate here. 28 | * @param argc The number of elements in the argv array. 29 | * @param argv The array of arguments, including the process. 30 | * @return The numeric result to return via console exit. 31 | */ 32 | using namespace mgbubble::cli; 33 | 34 | void my_impl(const http_message* hm) 35 | { 36 | auto&& reply = std::string(hm->body.p, hm->body.len); 37 | std::cout << reply << std::endl; 38 | } 39 | 40 | int main(int argc, char* argv[]) 41 | { 42 | std::string url{"127.0.0.1:8000/rpc"}; 43 | 44 | // HTTP request call commands 45 | HttpReq req(url, 3000, reply_handler(my_impl)); 46 | 47 | Json::Value jsonvar; 48 | Json::Value jsonopt; 49 | jsonvar["jsonrpc"] = "2.0"; 50 | jsonvar["id"] = 1; 51 | jsonvar["method"] = (argc > 1) ? argv[1] : "help"; 52 | jsonvar["params"] = Json::arrayValue; 53 | 54 | if (argc > 2) 55 | { 56 | for (int i = 2; i < argc; i++) 57 | { 58 | jsonvar["params"].append(argv[i]); 59 | } 60 | } 61 | 62 | req.post(jsonvar.toStyledString()); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /include/tinychain/database.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #pragma once 7 | #include 8 | #include 9 | #include 10 | #include 11 | //#include 12 | 13 | namespace tinychain 14 | { 15 | 16 | class database 17 | { 18 | public: 19 | database() {}; 20 | database(const database&) = default; 21 | database(database&&) = default; 22 | database& operator=(database&&) = default; 23 | database& operator=(const database&) = default; 24 | 25 | virtual void print(); 26 | void init(); 27 | void create_genesis_block(); 28 | 29 | protected: 30 | const char* db_name_ = "tinychain.db"; 31 | }; 32 | 33 | class chain_database: public database 34 | { 35 | public: 36 | 37 | chain_database() {}; 38 | chain_database(const chain_database&) = default; 39 | chain_database(chain_database&&) = default; 40 | chain_database& operator=(chain_database&&) = default; 41 | chain_database& operator=(const chain_database&) = default; 42 | 43 | void print(){ 44 | //for (auto& each : queue_ ) { 45 | // log::info("block")< 8 | #include 9 | #include 10 | #include 11 | 12 | namespace tinychain 13 | { 14 | 15 | class blockchain 16 | { 17 | public: 18 | typedef block::tx_list_t memory_pool_t; 19 | 20 | blockchain(uint16_t id = 1991):id_(id) { 21 | id_ = id; 22 | } 23 | blockchain(const blockchain&) = default; 24 | blockchain(blockchain&&) = default; 25 | blockchain& operator=(blockchain&&) = default; 26 | blockchain& operator=(const blockchain&) = default; 27 | 28 | void print(){ 29 | log::info("blockchain")<<"--------begin--------"; 30 | chain_.print(); 31 | log::info("blockchain")<<"--------end--------"; 32 | } 33 | void test(); 34 | 35 | void push_block(const block& new_block){ 36 | chain_.push(new_block); 37 | } 38 | 39 | uint64_t get_height(); 40 | 41 | block get_last_block(); 42 | 43 | bool get_block(sha256_t block_hash, block& out); 44 | 45 | bool get_tx(sha256_t tx_hash, tx& out); 46 | 47 | bool get_balance(address_t address, uint64_t balance); 48 | 49 | auto id() {return id_;} 50 | 51 | memory_pool_t pool() { return pool_; } 52 | void pool_reset(size_t times) { 53 | //TO FIX, dirty impl 54 | while(times--) 55 | pool_.erase(pool_.begin()); 56 | } 57 | 58 | void collect(tx& tx) { 59 | pool_.push_back(tx); 60 | log::info("blockchain-pool")<<"new tx:"< 2 | 3 | 4 | 5 | WebSocket Test 6 | 7 | 29 | 30 | 56 | 57 | 58 |
59 |

Tinychain Websocket Page

60 | 61 |

62 | This page demonstrates how Tinychain works. commands are: getnewaccount; startmining $address; send $address $amount; 63 |

64 | 65 |
66 |
67 | 68 |

69 | 70 | 71 |

72 |
73 | 74 | 75 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/utility/Compare.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS) - Metaverse. 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under the terms of the 5 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 6 | * License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License along with this program; if 13 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 14 | * 02110-1301, USA. 15 | */ 16 | #ifndef MVS_ASH_COMPARE_HPP 17 | #define MVS_ASH_COMPARE_HPP 18 | 19 | #include 20 | 21 | /** 22 | * @addtogroup Util 23 | * @{ 24 | */ 25 | 26 | namespace mgbubble { 27 | 28 | template 29 | class Comparable { 30 | public: 31 | friend constexpr bool operator==(const ValueT& lhs, const ValueT& rhs) noexcept 32 | { 33 | return lhs.compare(rhs) == 0; 34 | } 35 | 36 | friend constexpr bool operator!=(const ValueT& lhs, const ValueT& rhs) noexcept 37 | { 38 | return lhs.compare(rhs) != 0; 39 | } 40 | 41 | friend constexpr bool operator<(const ValueT& lhs, const ValueT& rhs) noexcept 42 | { 43 | return lhs.compare(rhs) < 0; 44 | } 45 | 46 | friend constexpr bool operator<=(const ValueT& lhs, const ValueT& rhs) noexcept 47 | { 48 | return lhs.compare(rhs) <= 0; 49 | } 50 | 51 | friend constexpr bool operator>(const ValueT& lhs, const ValueT& rhs) noexcept 52 | { 53 | return lhs.compare(rhs) > 0; 54 | } 55 | 56 | friend constexpr bool operator>=(const ValueT& lhs, const ValueT& rhs) noexcept 57 | { 58 | return lhs.compare(rhs) >= 0; 59 | } 60 | 61 | protected: 62 | ~Comparable() noexcept = default; 63 | }; 64 | 65 | template ::value>* = nullptr> 66 | constexpr int compare(EnumT lhs, EnumT rhs) noexcept 67 | { 68 | int i{}; 69 | if (lhs < rhs) { 70 | i = -1; 71 | } else if (lhs > rhs) { 72 | i = 1; 73 | } else { 74 | i = 0; 75 | } 76 | return i; 77 | } 78 | 79 | template ::value>* = nullptr> 81 | constexpr int compare(IntegralT lhs, IntegralT rhs) noexcept 82 | { 83 | int i{}; 84 | if (lhs < rhs) { 85 | i = -1; 86 | } else if (lhs > rhs) { 87 | i = 1; 88 | } else { 89 | i = 0; 90 | } 91 | return i; 92 | } 93 | 94 | } // http 95 | 96 | /** @} */ 97 | 98 | #endif // MVS_ASH_COMPARE_HPP 99 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/utility/Stream_buf.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS). 3 | * Copyright (C) 2013, 2016 Swirly Cloud Limited. 4 | * 5 | * This program is free software; you can redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 10 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program; if 14 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | #ifndef MVSD_STREAM_HPP 18 | #define MVSD_STREAM_HPP 19 | 20 | #include "mongoose/mongoose.h" 21 | 22 | #include 23 | 24 | /** 25 | * @addtogroup App 26 | * @{ 27 | */ 28 | 29 | namespace mgbubble { 30 | 31 | class StreamBuf : public std::streambuf { 32 | public: 33 | explicit StreamBuf(mbuf& buf) throw(std::bad_alloc); 34 | ~StreamBuf() noexcept override; 35 | 36 | // Copy. 37 | StreamBuf(const StreamBuf& rhs) = delete; 38 | StreamBuf& operator=(const StreamBuf& rhs) = delete; 39 | 40 | // Move. 41 | StreamBuf(StreamBuf&&) = delete; 42 | StreamBuf& operator=(StreamBuf&&) = delete; 43 | 44 | const char_type* data() const noexcept { return buf_.buf; } 45 | std::streamsize size() const noexcept { return buf_.len; } 46 | void reset() noexcept; 47 | void setContentLength(size_t pos, size_t len) noexcept; 48 | 49 | protected: 50 | int_type overflow(int_type c) noexcept override; 51 | 52 | std::streamsize xsputn(const char_type* s, std::streamsize count) noexcept override; 53 | 54 | private: 55 | mbuf& buf_; 56 | }; 57 | 58 | class OStream : public std::ostream { 59 | public: 60 | OStream(); 61 | ~OStream() noexcept override; 62 | 63 | // Copy. 64 | OStream(const OStream& rhs) = delete; 65 | OStream& operator=(const OStream& rhs) = delete; 66 | 67 | // Move. 68 | OStream(OStream&&) = delete; 69 | OStream& operator=(OStream&&) = delete; 70 | 71 | StreamBuf* rdbuf() const noexcept { return static_cast(std::ostream::rdbuf()); } 72 | const char_type* data() const noexcept { return rdbuf()->data(); } 73 | std::streamsize size() const noexcept { return rdbuf()->size(); } 74 | StreamBuf* rdbuf(StreamBuf* sb) noexcept 75 | { 76 | return static_cast(std::ostream::rdbuf(sb)); 77 | } 78 | void reset(int status, const char* reason,const char *content_type = "text/plain",const char *charset = "utf-8") noexcept; 79 | void setContentLength() noexcept; 80 | 81 | private: 82 | size_t headSize_{0}; 83 | size_t lengthAt_{0}; 84 | }; 85 | 86 | } // http 87 | 88 | /** @} */ 89 | 90 | #endif // MVSD_STREAM_HPP 91 | -------------------------------------------------------------------------------- /src/lib/utility/Stream_buf.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS). 3 | * Copyright (C) 2013, 2016 Swirly Cloud Limited. 4 | * 5 | * This program is free software; you can redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 10 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program; if 14 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | using namespace std; 23 | 24 | namespace mgbubble { 25 | 26 | StreamBuf::StreamBuf(mbuf& buf) throw(bad_alloc) : buf_(buf) 27 | { 28 | if (!buf_.buf) { 29 | // Pre-allocate buffer. 30 | mbuf_init(&buf_, 4096); 31 | if (!buf_.buf) { 32 | throw bad_alloc(); 33 | } 34 | } 35 | } 36 | 37 | StreamBuf::~StreamBuf() noexcept = default; 38 | 39 | void StreamBuf::reset() noexcept 40 | { 41 | buf_.len = 0; 42 | } 43 | 44 | void StreamBuf::setContentLength(size_t pos, size_t len) noexcept 45 | { 46 | char* ptr{buf_.buf + pos}; 47 | do { 48 | --ptr; 49 | *ptr = '0' + len % 10; 50 | len /= 10; 51 | } while (len > 0); 52 | } 53 | 54 | StreamBuf::int_type StreamBuf::overflow(int_type c) noexcept 55 | { 56 | if (c != traits_type::eof()) { 57 | const char z = c; 58 | if (mbuf_append(&buf_, &z, 1) != 1) { 59 | c = traits_type::eof(); 60 | } 61 | } 62 | return c; 63 | } 64 | 65 | streamsize StreamBuf::xsputn(const char_type* s, streamsize count) noexcept 66 | { 67 | return mbuf_append(&buf_, s, count); 68 | } 69 | 70 | OStream::OStream() : ostream{nullptr} 71 | { 72 | } 73 | 74 | OStream::~OStream() noexcept = default; 75 | 76 | void OStream::reset(int status, const char* reason,const char *content_type,const char *charset) noexcept 77 | { 78 | rdbuf()->reset(); 79 | mgbubble::reset(*this); 80 | 81 | // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF. Use 10 space place-holder for 82 | // content length. RFC2616 states that field value MAY be preceded by any amount of LWS, though a 83 | // single SP is preferred. 84 | *this << "HTTP/1.1 " << status << ' ' << reason << "\r\nContent-Type: "<< content_type<<";charset="<setContentLength(lengthAt_, size() - headSize_); 92 | } 93 | 94 | } // mgbubble 95 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | PROJECT(tinychain) 3 | 4 | SET(CMAKE_VERBOSE_MAKEFILE 1) 5 | 6 | SET(ENABLE_SHARED_LIBS OFF CACHE BOOL "Enable shared libs.") 7 | SET(MG_ENABLE_DEBUG OFF CACHE BOOL "Enable Mongoose debug.") 8 | 9 | IF(NOT CMAKE_BUILD_TYPE) 10 | SET(CMAKE_BUILD_TYPE DEBUG) 11 | #SET(CMAKE_BUILD_TYPE RELEASE) 12 | #SET(CMAKE_BUILD_TYPE RELWITHDEBINFO) 13 | #SET(CMAKE_BUILD_TYPE MINSIZEREL) 14 | ENDIF() 15 | 16 | # Enable for use with clang-tidy. 17 | IF(NOT CMAKE_EXPORT_COMPILE_COMMANDS) 18 | SET(CMAKE_EXPORT_COMPILE_COMMANDS ON) 19 | ENDIF() 20 | 21 | STRING(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE) 22 | 23 | # ----------------- common Definitions ------ 24 | IF(NOT WIN32) 25 | SET(COMMON_WARN "-Wall -Werror -Wstrict-aliasing=2 -Wno-unused-parameter -Wno-unused-variable -Wno-type-limits -Wno-deprecated-register -Wno-deprecated-declarations") 26 | SET(COMMON_FLAGS "-fstrict-aliasing -fvisibility=hidden") 27 | SET(COMMON_LIBS "-pthread") 28 | SET(COMMON_ARGS "${COMMON_FLAGS} ${COMMON_WARN} ${COMMON_LIBS}") 29 | ENDIF() 30 | 31 | # --------------- Compiler ------------------ 32 | IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 33 | SET(CMAKE_C_FLAGS "-std=c11 ${COMMON_ARGS}") 34 | SET(CMAKE_CXX_FLAGS "-std=c++14 ${COMMON_ARGS} -fno-enforce-eh-specs -fnothrow-opt -Wno-reorder -Wno-ignored-qualifiers -Wno-unused-function") 35 | ELSEIF("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") 36 | SET(CMAKE_C_FLAGS "-std=c11 ${COMMON_ARGS}") 37 | SET(CMAKE_CXX_FLAGS "-std=c++14 ${COMMON_ARGS} -Wno-reorder -Wno-unused-function -Wno-unused-command-line-argument") 38 | ENDIF() 39 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fPIC") 40 | 41 | # --------------- Definitions ------------------ 42 | ADD_DEFINITIONS(-DBOOST_NO_AUTO_PTR=1 -DBOOST_NO_TYPEID=1) 43 | 44 | IF(CMAKE_BUILD_TYPE STREQUAL "DEBUG") 45 | ADD_DEFINITIONS(-DMVS_DEBUG=1) 46 | ENDIF() 47 | 48 | SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin") 49 | SET(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib") 50 | 51 | # --------------- REQUIREMENTS --------------------- 52 | FILE(MAKE_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") 53 | FILE(MAKE_DIRECTORY "${LIBRARY_OUTPUT_PATH}") 54 | 55 | SET(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/etc") 56 | #SET(CMAKE_INSTALL_PREFIX ${PROJECT_BINARY_DIR}) 57 | SET(CMAKE_INSTALL_PREFIX "/usr/local/tinychain") 58 | 59 | set(Boost_USE_STATIC_LIBS ON) 60 | FIND_PACKAGE(Boost 1.56 REQUIRED COMPONENTS date_time filesystem) 61 | #system program_options) 62 | INCLUDE_DIRECTORIES("${Boost_INCLUDE_DIRS}") 63 | 64 | # ------------------ includes -------------------- 65 | INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/contrib") 66 | INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include") 67 | 68 | IF(ENABLE_SHARED_LIBS) 69 | SET(mongoose_LIBRARY mongoose_shared) 70 | SET(jsoncpp_LIBRARY jsoncpp_shared) 71 | ELSE() 72 | SET(mongoose_LIBRARY mongoose_static) 73 | SET(jsoncpp_LIBRARY jsoncpp_static) 74 | ENDIF() 75 | 76 | IF(WIN32) 77 | INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/contrib/sqlite") 78 | IF(ENABLE_SHARED_LIBS) 79 | SET(sqlite_LIBRARY sqlite_shared) 80 | ELSE() 81 | SET(sqlite_LIBRARY sqlite_static) 82 | ENDIF() 83 | ENDIF() 84 | 85 | ENABLE_TESTING() 86 | 87 | ADD_SUBDIRECTORY(contrib) 88 | ADD_SUBDIRECTORY(src) 89 | ADD_SUBDIRECTORY(cli-tinychain) 90 | 91 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/RestServ.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | namespace mgbubble{ 12 | 13 | 14 | class RestServ : public Mgr 15 | { 16 | public: 17 | explicit RestServ(const char* webroot, tinychain::node& node):node_(node) 18 | { 19 | memset(&httpoptions_, 0x00, sizeof(httpoptions_)); 20 | document_root_ = webroot; 21 | httpoptions_.document_root = document_root_.c_str(); 22 | } 23 | ~RestServ() noexcept {}; 24 | 25 | void run() { 26 | for (;;) 27 | this->poll(1000); 28 | } 29 | 30 | // Copy. 31 | RestServ(const RestServ& rhs) = delete; 32 | RestServ& operator=(const RestServ& rhs) = delete; 33 | 34 | // Move. 35 | RestServ(RestServ&&) = delete; 36 | RestServ& operator=(RestServ&&) = delete; 37 | 38 | //reset 39 | void reset(HttpMessage& data) noexcept; 40 | 41 | //request 42 | void httpStatic (mg_connection& nc, HttpMessage data); 43 | void httpRequest (mg_connection& nc, HttpMessage data); 44 | void httpRpcRequest (mg_connection& nc, HttpMessage data); 45 | void websocketBroadcast (mg_connection& nc, const char* msg, size_t len); 46 | void websocketSend(mg_connection* nc, const char* msg, size_t len); 47 | void websocketSend(mg_connection& nc, WebsocketMessage ws); 48 | 49 | // http session 50 | bool user_auth(mg_connection& nc, HttpMessage data); 51 | mg_serve_http_opts& get_httpoptions(){return httpoptions_;} 52 | std::shared_ptr get_from_session_list(HttpMessage data); 53 | bool remove_from_session_list(HttpMessage data); 54 | std::shared_ptr push_session(HttpMessage data); 55 | bool check_sessions(); 56 | 57 | std::pair user_check(HttpMessage &data) 58 | { 59 | auto user = data.header("user"); 60 | auto password = data.header("pass"); 61 | 62 | if (user.empty() || password.empty()) { 63 | throw std::logic_error("authorisation required"); 64 | } 65 | return std::make_pair(user, password); 66 | } 67 | 68 | 69 | private: 70 | enum : int { 71 | // Method values are represented as powers of two for simplicity. 72 | MethodGet = 1 << 0, 73 | MethodPost = 1 << 1, 74 | MethodPut = 1 << 2, 75 | MethodDelete = 1 << 3, 76 | // Method value mask. 77 | MethodMask = MethodGet | MethodPost | MethodPut | MethodDelete, 78 | 79 | // Subsequent bits represent matching components. 80 | MatchMethod = 1 << 4, 81 | MatchUri = 1 << 5, 82 | // Match result mask. 83 | MatchMask = MatchMethod | MatchUri 84 | }; 85 | 86 | bool isSet(int bs) const noexcept { return (state_ & bs) == bs; } 87 | 88 | // http 89 | mg_serve_http_opts httpoptions_; 90 | #if MVS_DEBUG 91 | constexpr static const double SESSION_TTL = 900.0; 92 | #else 93 | constexpr static const double SESSION_TTL = 240.0; 94 | #endif 95 | std::list< std::shared_ptr > session_list_; 96 | 97 | // config 98 | static thread_local OStream out_; 99 | static thread_local Tokeniser<'/'> uri_; 100 | static thread_local int state_; 101 | //const char* const servername_{"Http-Metaverse"}; 102 | std::string document_root_; 103 | 104 | tinychain::node& node_; 105 | }; 106 | 107 | } // mgbubble 108 | -------------------------------------------------------------------------------- /src/consensus.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace tinychain 13 | { 14 | 15 | void miner::start(address_t& addr){ 16 | for(;;) { 17 | block new_block; 18 | 19 | // 未找到,继续找 20 | if (!pow_once(new_block, addr)) { 21 | continue; 22 | } 23 | 24 | // 需要在pool中移除已经被打包的交易 25 | chain_.pool_reset(new_block.header_.tx_count); 26 | 27 | // 调用网络广播 28 | //ws_send(new_block.to_json().toStyledString()); 29 | 30 | // 本地存储 31 | chain_.push_block(new_block); 32 | } 33 | } 34 | 35 | tx miner::create_coinbase_tx(address_t& addr) { 36 | // TODO 37 | return tx{addr}; 38 | } 39 | 40 | bool miner::pow_once(block& new_block, address_t& addr) { 41 | 42 | auto&& pool = chain_.pool(); 43 | 44 | auto&& prev_block = chain_.get_last_block(); 45 | 46 | // 填充新块 47 | new_block.header_.height = prev_block.header_.height + 1; 48 | new_block.header_.prev_hash = prev_block.header_.hash; 49 | 50 | new_block.header_.timestamp = get_now_timestamp(); 51 | 52 | new_block.header_.tx_count = pool.size(); 53 | 54 | // 难度调整: 55 | // 控制每块速度,控制最快速度,大约10秒 56 | uint64_t time_peroid = new_block.header_.timestamp - prev_block.header_.timestamp; 57 | log::info("consensus") << "block time :" << time_peroid <<" s"; 58 | 59 | if (time_peroid <= 10u) { 60 | new_block.header_.difficulty = prev_block.header_.difficulty + 9000; 61 | } else { 62 | if (prev_block.header_.difficulty <= 3000) { 63 | new_block.header_.difficulty = prev_block.header_.difficulty + 9000; 64 | } else { 65 | new_block.header_.difficulty = prev_block.header_.difficulty - 3000; 66 | } 67 | } 68 | 69 | log::debug("consensus")<< prev_block.header_.difficulty; 70 | 71 | // 计算挖矿目标值,最大值除以难度就目标值 72 | uint64_t target = 0xffffffffffffffff / prev_block.header_.difficulty; 73 | 74 | // 设置coinbase交易, CHENHAO => 这里继续,设置coinbase,后续实现验证交易和区块。 75 | auto&& tx = create_coinbase_tx(addr); 76 | pool.push_back(tx); 77 | 78 | // 装载交易 79 | new_block.setup(pool); 80 | 81 | // 计算目标值 82 | for ( uint64_t n = 0; ; ++n) { 83 | //尝试候选目标值 84 | new_block.header_.nonce = n; 85 | auto&& jv_block = new_block.to_json(); 86 | auto&& can = to_sha256(jv_block); 87 | uint64_t ncan = std::stoull(can.substr(0, 16), 0, 16); //截断前16位,转换uint64 后进行比较 88 | 89 | // 找到了 90 | if (ncan < target) { 91 | new_block.header_.hash = can; 92 | //log::info("consensus") << "target:" << ncan; 93 | //log::info("consensus") << "new block :" << can; 94 | log::info("consensus") << "new block :" << jv_block.toStyledString(); 95 | return true; 96 | } 97 | } 98 | 99 | return false; 100 | } 101 | 102 | bool validate_tx(blockchain& chain, const tx& new_tx) { 103 | // TODO 104 | // input exsited? 105 | auto&& inputs = new_tx.inputs(); 106 | for (auto& each : inputs) { 107 | 108 | tx pt; 109 | if (!chain.get_tx(std::get<0>(each), pt)) { 110 | return false; 111 | } 112 | 113 | log::info("consensus")< 18 | 19 | #include 20 | 21 | using namespace std; 22 | 23 | namespace mgbubble { 24 | 25 | ServException::~ServException() noexcept = default; 26 | 27 | void ServException::toJson(int status, const char* reason, const char* detail, ostream& os) 28 | { 29 | os << "{\"status\":" << status // 30 | << ",\"reason\":\"" << reason // 31 | << "\",\"detail\":\"" << detail // 32 | << "\"}"; 33 | } 34 | 35 | BadRequestException::~BadRequestException() noexcept = default; 36 | 37 | int BadRequestException::httpStatus() const noexcept 38 | { 39 | return 400; 40 | } 41 | 42 | const char* BadRequestException::httpReason() const noexcept 43 | { 44 | return "Bad Request"; 45 | } 46 | 47 | AlreadyExistsException::~AlreadyExistsException() noexcept = default; 48 | 49 | RefAlreadyExistsException::~RefAlreadyExistsException() noexcept = default; 50 | 51 | InvalidException::~InvalidException() noexcept = default; 52 | 53 | ForbiddenException::~ForbiddenException() noexcept = default; 54 | 55 | int ForbiddenException::httpStatus() const noexcept 56 | { 57 | return 403; 58 | } 59 | 60 | const char* ForbiddenException::httpReason() const noexcept 61 | { 62 | return "Forbidden"; 63 | } 64 | 65 | InternalException::~InternalException() noexcept = default; 66 | 67 | int InternalException::httpStatus() const noexcept 68 | { 69 | return 500; 70 | } 71 | 72 | const char* InternalException::httpReason() const noexcept 73 | { 74 | return "Internal Server Error"; 75 | } 76 | 77 | MethodNotAllowedException::~MethodNotAllowedException() noexcept = default; 78 | 79 | int MethodNotAllowedException::httpStatus() const noexcept 80 | { 81 | return 405; 82 | } 83 | 84 | const char* MethodNotAllowedException::httpReason() const noexcept 85 | { 86 | return "Method Not Allowed"; 87 | } 88 | 89 | NotFoundException::~NotFoundException() noexcept = default; 90 | 91 | int NotFoundException::httpStatus() const noexcept 92 | { 93 | return 404; 94 | } 95 | 96 | const char* NotFoundException::httpReason() const noexcept 97 | { 98 | return "Not Found"; 99 | } 100 | 101 | ServiceUnavailableException::~ServiceUnavailableException() noexcept = default; 102 | 103 | int ServiceUnavailableException::httpStatus() const noexcept 104 | { 105 | return 503; 106 | } 107 | 108 | const char* ServiceUnavailableException::httpReason() const noexcept 109 | { 110 | return "Service Unavailable"; 111 | } 112 | 113 | UnauthorizedException::~UnauthorizedException() noexcept = default; 114 | 115 | int UnauthorizedException::httpStatus() const noexcept 116 | { 117 | return 401; 118 | } 119 | 120 | const char* UnauthorizedException::httpReason() const noexcept 121 | { 122 | return "Unauthorized"; 123 | } 124 | 125 | } // mgbubble 126 | -------------------------------------------------------------------------------- /src/tinychain.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #include 7 | #include 8 | 9 | namespace tinychain { 10 | 11 | // 从公钥推导地址的函数 12 | address_t key_to_address(const public_key_t& public_key) { 13 | // 首先获取标准格式的公钥 14 | std::string x509_pubk; //binary pubk as x.509 15 | CryptoPP::StringSink ss(x509_pubk); 16 | public_key.Save(ss); 17 | 18 | // 进行一次MD5作为地址 19 | return to_md5(x509_pubk); 20 | 21 | #if 0 22 | CryptoPP::Base64Encoder pubk_slink(new CryptoPP::StringSink(encoded_pubk), false); 23 | public_key.DEREncode(pubk_slink); 24 | pubk_slink.MessageEnd(); 25 | // sha256 public key 作为地址,和sha256区别开来,并且简短 26 | auto&& sha256_pubk = sha256(encoded_pubk); 27 | return sha256_pubk; 28 | #endif 29 | } 30 | 31 | address_t key_to_address(const private_key_t& private_key) { 32 | public_key_t public_key(private_key); 33 | return key_to_address(public_key); 34 | } 35 | 36 | // 获取时间戳的工具函数 37 | uint64_t get_now_timestamp() { 38 | boost::posix_time::ptime epoch(boost::gregorian::date(1970, boost::gregorian::Jan, 1)); 39 | boost::posix_time::time_duration time_from_epoch = boost::posix_time::second_clock::universal_time() - epoch; 40 | return time_from_epoch.total_seconds(); 41 | } 42 | 43 | // 获取随机数的工具函数 44 | uint64_t pseudo_random(){ 45 | std::random_device device; 46 | std::uniform_int_distribution distribution; 47 | return distribution(device); 48 | } 49 | 50 | sha256_t to_sha256(Json::Value jv){ 51 | Json::StreamWriterBuilder builder; 52 | std::ostringstream oss; 53 | std::unique_ptr writer(builder.newStreamWriter()); 54 | writer->write(jv, &oss); 55 | return sha256(oss.str()); 56 | } 57 | 58 | md5_t to_md5(const std::string& message){ 59 | uint8_t digest[ CryptoPP::Weak::MD5::DIGESTSIZE ]; 60 | 61 | CryptoPP::Weak::MD5 hash; 62 | hash.CalculateDigest( digest, (const uint8_t*)message.c_str(), message.length() ); 63 | 64 | CryptoPP::HexEncoder encoder; 65 | std::string output; 66 | 67 | encoder.Attach( new CryptoPP::StringSink( output ) ); 68 | encoder.Put( digest, sizeof(digest) ); 69 | encoder.MessageEnd(); 70 | 71 | return output; 72 | } 73 | 74 | // #################### 以下类的成员函数实现 ################## 75 | 76 | Json::Value tx::item_to_json (input_item_t in) { 77 | Json::Value root; 78 | root["hash"] = std::get<0>(in); 79 | root["index"] = std::get<1>(in); 80 | root["script_sign"] = std::get<2>(in); 81 | return root; 82 | } 83 | Json::Value tx::item_to_json (output_item_t out) { 84 | Json::Value root; 85 | root["address"] = std::get<0>(out); 86 | root["value"] = std::get<1>(out); 87 | root["script_pubkey"] = std::get<2>(out); 88 | return root; 89 | } 90 | 91 | Json::Value tx::to_json(){ 92 | Json::Value root; 93 | 94 | Json::Value inputs; 95 | for (auto& each: inputs_) { 96 | inputs.append(item_to_json(each)); 97 | } 98 | root["inputs"] = inputs; 99 | 100 | Json::Value outputs; 101 | for (auto& each: outputs_) { 102 | outputs.append(item_to_json(each)); 103 | } 104 | root["outputs"] = outputs; 105 | hash_ = to_sha256(root); 106 | root["hash"] = hash_; 107 | 108 | return root; 109 | } 110 | 111 | tx::tx(address_t& address) { 112 | // coinbase tx: TODO 113 | auto&& input_item = std::make_tuple("00000000000000000000000000000000", 0, "0ffffffffffffff"); 114 | inputs_.push_back(input_item); 115 | 116 | // build tx 117 | auto&& ouput_item = std::make_tuple(address, 1000, "1ffffffffffffffff"); 118 | outputs_.push_back(ouput_item); 119 | 120 | // hash 121 | to_json(); 122 | } 123 | 124 | tx::tx(address_t& address, uint64_t amount) { 125 | //get_balance_from blokchain, P2PKH 126 | //TODO 127 | auto&& input_item = std::make_tuple(to_md5(address), 0, "0ffffffffffffff"); 128 | inputs_.push_back(input_item); 129 | 130 | // build tx 131 | auto&& ouput_item = std::make_tuple(address, amount, "1ffffffffffffffff"); 132 | outputs_.push_back(ouput_item); 133 | 134 | // hash 135 | to_json(); 136 | } 137 | 138 | } //tinychain 139 | -------------------------------------------------------------------------------- /include/tinychain/logging.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | /** 7 | * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS) 8 | * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS) 9 | * 10 | * This file is part of metaverse. 11 | * 12 | * metaverse is free software: you can redistribute it and/or modify 13 | * it under the terms of the GNU Affero General Public License with 14 | * additional permissions to the one published by the Free Software 15 | * Foundation, either version 3 of the License, or (at your option) 16 | * any later version. For more information see LICENSE. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU Affero General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Affero General Public License 24 | * along with this program. If not, see . 25 | */ 26 | #ifndef MVS_NETWORK_LOGGING_HPP 27 | #define MVS_NETWORK_LOGGING_HPP 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | namespace tinychain { 37 | 38 | class log 39 | { 40 | public: 41 | enum class level 42 | { 43 | trace, 44 | debug, 45 | info, 46 | warning, 47 | error, 48 | fatal, 49 | null 50 | }; 51 | 52 | typedef std::function 53 | functor; 54 | 55 | log(level value, const std::string& domain); 56 | log(log&& other); 57 | ~log(); 58 | 59 | /// Clear all log configuration. 60 | static void clear(); 61 | 62 | /// Convert the log level value to English text. 63 | static std::string to_text(level value); 64 | 65 | // Stream to these functions. 66 | static log trace(const std::string& domain); 67 | static log debug(const std::string& domain); 68 | static log info(const std::string& domain); 69 | static log warning(const std::string& domain); 70 | static log error(const std::string& domain); 71 | static log fatal(const std::string& domain); 72 | 73 | template 74 | log& operator<<(Type const& value) 75 | { 76 | stream_ << value; 77 | return *this; 78 | } 79 | 80 | /// Set the output functor for this log instance. 81 | void set_output_function(functor value); 82 | 83 | private: 84 | typedef std::map destinations; 85 | 86 | static void output_ignore(level value, const std::string& domain, 87 | const std::string& body); 88 | static void output_cout(level value, const std::string& domain, 89 | const std::string& body); 90 | static void output_cerr(level value, const std::string& domain, 91 | const std::string& body); 92 | 93 | static void to_stream(std::ostream& out, level value, 94 | const std::string& domain, const std::string& body); 95 | 96 | static destinations destinations_; 97 | 98 | level level_; 99 | std::string domain_; 100 | std::ostringstream stream_; 101 | }; 102 | 103 | 104 | /// Set up global logging. 105 | void initialize_logging(std::ofstream& debug, std::ofstream& error, 106 | std::ostream& output_stream, std::ostream& error_stream, std::string level = "DEBUG"); 107 | 108 | /// Class Logger 109 | class Logger{ 110 | #define self Logger 111 | 112 | public: 113 | self() noexcept 114 | { 115 | initialize_logging(debug_log_, error_log_, std::cout, std::cerr); 116 | } 117 | 118 | self(const self&) = delete; 119 | self(const self&&) = delete; 120 | 121 | ~self() noexcept 122 | { 123 | log::clear(); 124 | debug_log_.close(); 125 | error_log_.close(); 126 | } 127 | 128 | public: 129 | /// Constant for logging file open mode (append output). 130 | static constexpr std::ofstream::openmode log_open_mode = 131 | std::ofstream::out | std::ofstream::app; 132 | 133 | private: 134 | std::ofstream debug_log_{"debug.log", log_open_mode}; 135 | std::ofstream error_log_{"error.log", log_open_mode}; 136 | 137 | #undef self 138 | };// class Logger 139 | 140 | } // namespace libbitcoin 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/MongooseCli.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS). 3 | * Copyright (C) 2013, 2016 Swirly Cloud Limited. 4 | * 5 | * This program is free software; you can redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 10 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program; if 14 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | #ifndef MVSD_MONGOOSECLI_HPP 18 | #define MVSD_MONGOOSECLI_HPP 19 | 20 | #include 21 | #include 22 | #include "mongoose/mongoose.h" 23 | 24 | namespace mgbubble { 25 | namespace cli { 26 | 27 | typedef std::function reply_handler; 28 | 29 | template 30 | class MgrCli { 31 | public: 32 | // Copy. 33 | MgrCli(const MgrCli&) = delete; 34 | MgrCli& operator=(const MgrCli&) = delete; 35 | 36 | // Move. 37 | MgrCli(MgrCli&&) = delete; 38 | MgrCli& operator=(MgrCli&&) = delete; 39 | 40 | inline time_t poll(int milli) { return mg_mgr_poll(&mgr_, milli); } 41 | 42 | protected: 43 | MgrCli() noexcept { mg_mgr_init(&mgr_, this); } 44 | ~MgrCli() noexcept { mg_mgr_free(&mgr_); } 45 | 46 | static void ev_handler(mg_connection* nc, int ev, void *ev_data) { 47 | auto* hm = static_cast(ev_data); 48 | auto* self = static_cast(nc->user_data);//this 49 | 50 | switch (ev) { 51 | case MG_EV_CONNECT: 52 | if (* (int *) ev_data != 0) { 53 | fprintf(stderr, "connect[%s] failed: %s\n", 54 | self->get_url().c_str(), strerror(* (int *) ev_data)); 55 | self->exit(); 56 | } 57 | break; 58 | case MG_EV_HTTP_REPLY: 59 | nc->flags |= MG_F_CLOSE_IMMEDIATELY; 60 | self->reply(hm); 61 | self->exit(); 62 | break; 63 | default: 64 | break; 65 | } 66 | } 67 | 68 | mg_mgr mgr_; 69 | }; 70 | 71 | class HttpReq : public MgrCli 72 | { 73 | public: 74 | explicit HttpReq(const std::string& url, int milli, reply_handler&& oreply) 75 | :url_(url), reply(oreply){ 76 | memset(&opts_, 0x00, sizeof(opts_)); 77 | opts_.user_data = reinterpret_cast(this); 78 | 79 | if (milli > 0) 80 | milli_ = milli; 81 | } 82 | ~HttpReq() noexcept {} 83 | 84 | //void got_reply(http_message* msg) { reply(msg); } 85 | 86 | const std::string& get_url(){ return url_; } 87 | void set_url(const std::string& other){ url_ = other; } 88 | void set_url(std::string&& other){ url_ = other; } 89 | void exit(){ exit_ = true; } 90 | void reset(){ exit_ = false; } 91 | 92 | void get() { 93 | conn_ = mg_connect_http_opt(&mgr_, ev_handler, opts_, url_.c_str(), NULL, NULL); 94 | while (!exit_){ 95 | poll(milli_); 96 | } 97 | } 98 | void post(std::string&& data) { post(data); } 99 | void post(const std::string& data) { 100 | conn_ = mg_connect_http_opt(&mgr_, ev_handler, opts_, url_.c_str(), NULL, data.c_str()); 101 | while (!exit_){ 102 | poll(milli_); 103 | } 104 | } 105 | void post(std::string&& header, std::string&& data) { post(header, data); } 106 | void post(const std::string& header, const std::string& data) { 107 | conn_ = mg_connect_http_opt(&mgr_, ev_handler, opts_, url_.c_str(), header.c_str(), data.c_str()); 108 | while (!exit_){ 109 | poll(milli_); 110 | } 111 | } 112 | 113 | reply_handler reply; 114 | private: 115 | int milli_{3000}; 116 | bool exit_{false}; 117 | mg_connect_opts opts_; 118 | mg_connection* conn_{nullptr}; 119 | std::string url_; 120 | }; 121 | 122 | } // mg 123 | } // http 124 | 125 | /** @} */ 126 | 127 | #endif // MVSD_MONGOOSECLI_HPP 128 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/utility/Stream.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS) - Metaverse. 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under the terms of the 5 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 6 | * License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License along with this program; if 13 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 14 | * 02110-1301, USA. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | /** 24 | * @addtogroup Util 25 | * @{ 26 | */ 27 | 28 | namespace mgbubble { 29 | 30 | MVS_API void reset(std::ostream& os) noexcept; 31 | 32 | template 33 | class StringBuf : public std::streambuf { 34 | public: 35 | StringBuf() noexcept { reset(); } 36 | ~StringBuf() noexcept override = default; 37 | 38 | // Copy. 39 | StringBuf(const StringBuf& rhs) = delete; 40 | StringBuf& operator=(const StringBuf& rhs) = delete; 41 | 42 | // Move. 43 | StringBuf(StringBuf&&) = delete; 44 | StringBuf& operator=(StringBuf&&) = delete; 45 | 46 | const char* data() const noexcept { return pbase(); } 47 | bool empty() const noexcept { return pbase() == pptr(); } 48 | std::size_t size() const noexcept { return pptr() - pbase(); } 49 | string_view str() const noexcept { return {data(), size()}; } 50 | void reset() noexcept { setp(buf_, buf_ + MaxN); }; 51 | private: 52 | char buf_[MaxN]; 53 | }; 54 | 55 | template 56 | class StringBuilder : public std::ostream { 57 | public: 58 | StringBuilder() : std::ostream{nullptr} { rdbuf(&buf_); } 59 | ~StringBuilder() noexcept override = default; 60 | 61 | // Copy. 62 | StringBuilder(const StringBuilder& rhs) = delete; 63 | StringBuilder& operator=(const StringBuilder& rhs) = delete; 64 | 65 | // Move. 66 | StringBuilder(StringBuilder&&) = delete; 67 | StringBuilder& operator=(StringBuilder&&) = delete; 68 | 69 | const char* data() const noexcept { return buf_.data(); } 70 | bool empty() const noexcept { return buf_.empty(); } 71 | std::size_t size() const noexcept { return buf_.size(); } 72 | string_view str() const noexcept { return buf_.str(); } 73 | operator string_view() const noexcept { return buf_.str(); } 74 | void reset() noexcept 75 | { 76 | buf_.reset(); 77 | mgbubble::reset(*this); 78 | }; 79 | 80 | private: 81 | StringBuf buf_; 82 | }; 83 | 84 | template 85 | auto& operator<<(StringBuilder& sb, ValueT&& val) 86 | { 87 | static_cast(sb) << std::forward(val); 88 | return sb; 89 | } 90 | 91 | /** 92 | * Stream joiner. This is a simplified version of std::experimental::ostream_joiner, intended as a 93 | * placeholder until TS v2 is more widely available. 94 | */ 95 | class MVS_API OStreamJoiner { 96 | public: 97 | using char_type = char; 98 | using traits_type = std::char_traits; 99 | using ostream_type = std::ostream; 100 | using value_type = void; 101 | using difference_type = void; 102 | using pointer = void; 103 | using reference = void; 104 | using iterator_category = std::output_iterator_tag; 105 | 106 | OStreamJoiner(std::ostream& os, const char delim) noexcept : os_{&os}, delim_{delim} {} 107 | ~OStreamJoiner() noexcept; 108 | 109 | // Copy. 110 | OStreamJoiner(const OStreamJoiner&) = default; 111 | OStreamJoiner& operator=(const OStreamJoiner&) = default; 112 | 113 | // Move. 114 | OStreamJoiner(OStreamJoiner&&) = default; 115 | OStreamJoiner& operator=(OStreamJoiner&&) = default; 116 | 117 | template 118 | OStreamJoiner& operator=(const ValueT& value) 119 | { 120 | if (!first_) { 121 | *os_ << delim_; 122 | } 123 | first_ = false; 124 | *os_ << value; 125 | return *this; 126 | } 127 | OStreamJoiner& operator*() noexcept { return *this; } 128 | OStreamJoiner& operator++() noexcept { return *this; } 129 | OStreamJoiner& operator++(int)noexcept { return *this; } 130 | 131 | private: 132 | std::ostream* os_; 133 | char delim_; 134 | bool first_{true}; 135 | }; 136 | 137 | } // http 138 | 139 | /** @} */ 140 | 141 | -------------------------------------------------------------------------------- /src/lib/sha256.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace tinychain { 6 | 7 | const unsigned int SHA256::sha256_k[64] = //UL = uint32 8 | {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 9 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 10 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 11 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 12 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 13 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 14 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 15 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 16 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 17 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 18 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 19 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 20 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 21 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 22 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 23 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; 24 | 25 | void SHA256::transform(const unsigned char *message, unsigned int block_nb) 26 | { 27 | uint32 w[64]; 28 | uint32 wv[8]; 29 | uint32 t1, t2; 30 | const unsigned char *sub_block; 31 | int i; 32 | int j; 33 | for (i = 0; i < (int) block_nb; i++) { 34 | sub_block = message + (i << 6); 35 | for (j = 0; j < 16; j++) { 36 | SHA2_PACK32(&sub_block[j << 2], &w[j]); 37 | } 38 | for (j = 16; j < 64; j++) { 39 | w[j] = SHA256_F4(w[j - 2]) + w[j - 7] + SHA256_F3(w[j - 15]) + w[j - 16]; 40 | } 41 | for (j = 0; j < 8; j++) { 42 | wv[j] = m_h[j]; 43 | } 44 | for (j = 0; j < 64; j++) { 45 | t1 = wv[7] + SHA256_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6]) 46 | + sha256_k[j] + w[j]; 47 | t2 = SHA256_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]); 48 | wv[7] = wv[6]; 49 | wv[6] = wv[5]; 50 | wv[5] = wv[4]; 51 | wv[4] = wv[3] + t1; 52 | wv[3] = wv[2]; 53 | wv[2] = wv[1]; 54 | wv[1] = wv[0]; 55 | wv[0] = t1 + t2; 56 | } 57 | for (j = 0; j < 8; j++) { 58 | m_h[j] += wv[j]; 59 | } 60 | } 61 | } 62 | 63 | void SHA256::init() 64 | { 65 | m_h[0] = 0x6a09e667; 66 | m_h[1] = 0xbb67ae85; 67 | m_h[2] = 0x3c6ef372; 68 | m_h[3] = 0xa54ff53a; 69 | m_h[4] = 0x510e527f; 70 | m_h[5] = 0x9b05688c; 71 | m_h[6] = 0x1f83d9ab; 72 | m_h[7] = 0x5be0cd19; 73 | m_len = 0; 74 | m_tot_len = 0; 75 | } 76 | 77 | void SHA256::update(const unsigned char *message, unsigned int len) 78 | { 79 | unsigned int block_nb; 80 | unsigned int new_len, rem_len, tmp_len; 81 | const unsigned char *shifted_message; 82 | tmp_len = SHA224_256_BLOCK_SIZE - m_len; 83 | rem_len = len < tmp_len ? len : tmp_len; 84 | memcpy(&m_block[m_len], message, rem_len); 85 | if (m_len + len < SHA224_256_BLOCK_SIZE) { 86 | m_len += len; 87 | return; 88 | } 89 | new_len = len - rem_len; 90 | block_nb = new_len / SHA224_256_BLOCK_SIZE; 91 | shifted_message = message + rem_len; 92 | transform(m_block, 1); 93 | transform(shifted_message, block_nb); 94 | rem_len = new_len % SHA224_256_BLOCK_SIZE; 95 | memcpy(m_block, &shifted_message[block_nb << 6], rem_len); 96 | m_len = rem_len; 97 | m_tot_len += (block_nb + 1) << 6; 98 | } 99 | 100 | void SHA256::final(unsigned char *digest) 101 | { 102 | unsigned int block_nb; 103 | unsigned int pm_len; 104 | unsigned int len_b; 105 | int i; 106 | block_nb = (1 + ((SHA224_256_BLOCK_SIZE - 9) 107 | < (m_len % SHA224_256_BLOCK_SIZE))); 108 | len_b = (m_tot_len + m_len) << 3; 109 | pm_len = block_nb << 6; 110 | memset(m_block + m_len, 0, pm_len - m_len); 111 | m_block[m_len] = 0x80; 112 | SHA2_UNPACK32(len_b, m_block + pm_len - 4); 113 | transform(m_block, block_nb); 114 | for (i = 0 ; i < 8; i++) { 115 | SHA2_UNPACK32(m_h[i], &digest[i << 2]); 116 | } 117 | } 118 | 119 | std::string sha256(const std::string& input) 120 | { 121 | unsigned char digest[SHA256::DIGEST_SIZE]; 122 | memset(digest,0,SHA256::DIGEST_SIZE); 123 | 124 | SHA256 ctx = SHA256(); 125 | ctx.init(); 126 | ctx.update( (unsigned char*)input.c_str(), input.length()); 127 | ctx.final(digest); 128 | 129 | char buf[2*SHA256::DIGEST_SIZE+1]; 130 | buf[2*SHA256::DIGEST_SIZE] = 0; 131 | for (uint32_t i = 0; i < SHA256::DIGEST_SIZE; i++) 132 | sprintf(buf+i*2, "%02x", digest[i]); 133 | return std::string(buf); 134 | } 135 | 136 | } // namespace tinychain 137 | -------------------------------------------------------------------------------- /src/lib/Mongoose.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS). 3 | * Copyright (C) 2013, 2016 Swirly Cloud Limited. 4 | * 5 | * This program is free software; you can redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 10 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program; if 14 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace mgbubble { 24 | 25 | void HttpMessage::data_to_arg() { 26 | 27 | auto vargv_to_argv = [this]() { 28 | // convert to char** argv 29 | int i = 0; 30 | for(auto& iter : this->vargv_){ 31 | if (i >= max_paramters){ 32 | break; 33 | } 34 | this->argv_[i++] = iter.c_str(); 35 | } 36 | argc_ = i; 37 | }; 38 | 39 | auto convert = [this](string_view method, string_view pramas){ 40 | 41 | if (!method.empty()){ 42 | this->vargv_.push_back({method.data(), method.size()}); 43 | } 44 | 45 | if (!pramas.empty()){ 46 | Tokeniser<' '> args; 47 | args.reset(pramas); 48 | 49 | // store args from ws message 50 | do { 51 | //skip spaces 52 | if (args.top().front() == ' '){ 53 | args.pop(); 54 | continue; 55 | } else if (std::iscntrl(args.top().front())){ 56 | break; 57 | } else { 58 | this->vargv_.push_back({args.top().data(), args.top().size()}); 59 | args.pop(); 60 | } 61 | }while(!args.empty()); 62 | } 63 | 64 | }; 65 | 66 | /* ******************************************* 67 | * application/json 68 | * {"method":"xxx", "params":""} 69 | * ******************************************/ 70 | if (uri() == "/rpc" || uri() == "/rpc/") 71 | { 72 | 73 | #if 0 74 | pt::ptree root; 75 | std::istringstream sin; 76 | sin.str({body().data(), body().size()}); 77 | pt::read_json(sin, root); 78 | auto&& method = root.get("method"); 79 | if (method.size()){ 80 | vargv_.push_back(method); 81 | } 82 | 83 | for (auto& each : root.get_child("params.")) { 84 | vargv_.push_back(each.second.data()); 85 | } 86 | #else 87 | minijson::const_buffer_context ctx(body().data(), body().size()); 88 | minijson::parse_object(ctx, 89 | [&, this](const char* key, minijson::value value){ 90 | minijson::dispatch (key) 91 | <<"method">> [&,this]{ 92 | std::string&& method = value.as_string(); 93 | if (method.size()){ 94 | vargv_.insert(vargv_.begin(), method); 95 | } 96 | } 97 | <<"params">> [&, this]{ 98 | minijson::parse_array(ctx, [&](minijson::value v) { 99 | std::string&& params = v.as_string(); 100 | if (params.size()) 101 | vargv_.push_back(params); 102 | }); 103 | } 104 | <> [&]{ minijson::ignore(ctx); }; 105 | }); 106 | #endif 107 | 108 | vargv_to_argv(); 109 | } 110 | 111 | /* ******************************************* 112 | * application/x-www-form-urlencoded 113 | * method=xxx¶ms=xxx 114 | * ******************************************/ 115 | if (uri().substr(0,4) == "/api") 116 | { 117 | std::array params{{0x00}}; 118 | auto len = mg_get_http_var(&impl_->body, "params", params.data(), params.max_size()); 119 | 120 | convert({nullptr, 0u}, 121 | {params.data(), static_cast(len)}); 122 | vargv_to_argv(); 123 | } 124 | 125 | } 126 | 127 | void WebsocketMessage::data_to_arg() { 128 | Tokeniser<' '> args; 129 | args.reset(+*impl_); 130 | 131 | // store args from ws message 132 | do { 133 | //skip spaces 134 | if (args.top().front() == ' '){ 135 | args.pop(); 136 | continue; 137 | } else if (std::iscntrl(args.top().front())){ 138 | break; 139 | } else { 140 | this->vargv_.push_back({args.top().data(), args.top().size()}); 141 | args.pop(); 142 | } 143 | }while(!args.empty()); 144 | 145 | // convert to char** argv 146 | int i = 0; 147 | for(auto& iter : vargv_){ 148 | if (i >= max_paramters){ 149 | break; 150 | } 151 | argv_[i++] = iter.c_str(); 152 | } 153 | argc_ = i; 154 | } 155 | 156 | void ToCommandArg::add_arg(std::string&& outside) 157 | { 158 | vargv_.push_back(outside); 159 | argc_++; 160 | } 161 | 162 | } // mgbubble 163 | -------------------------------------------------------------------------------- /src/database.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #include 7 | #include 8 | 9 | namespace tinychain 10 | { 11 | 12 | // ----------------------- class databse ------------------- 13 | void database::print(){ 14 | sqlite3pp::database db_conn{db_name_}; 15 | log::debug("database")<<"====== Print begin ====="; 16 | try{ 17 | sqlite3pp::query qry(db_conn, "SELECT * FROM key_pairs"); 18 | log::debug("database")<< "column count:"<< qry.column_count(); 19 | 20 | for (int i = 0; i < qry.column_count(); ++i) { 21 | log::debug("database") << "columm name:" << qry.column_name(i); 22 | } 23 | 24 | for (sqlite3pp::query::iterator i = qry.begin(); i != qry.end(); ++i) { 25 | for (int j = 0; j < qry.column_count(); ++j) { 26 | log::debug("database")<< (*i).get(j); 27 | } 28 | } 29 | } catch (std::exception& ex) { 30 | db_conn.disconnect(); 31 | log::error("database")<<"disconnect db with error:"<< ex.what(); 32 | } 33 | db_conn.disconnect(); 34 | log::debug("database")<<"====== Print end ====="; 35 | } 36 | 37 | void database::create_genesis_block() { 38 | 39 | block genesis_block; 40 | 41 | genesis_block.header_.prev_hash = "0000000000000000000000000000000000000000000000000000000000000000"; 42 | genesis_block.header_.timestamp = get_now_timestamp(); 43 | genesis_block.header_.tx_count = 1; 44 | genesis_block.header_.difficulty = 1; 45 | 46 | genesis_block.header_.hash = to_sha256(genesis_block.to_json()); 47 | 48 | // TO BE Improved. => Same one 49 | chain_database chain; 50 | chain.push(genesis_block); 51 | } 52 | 53 | 54 | void database::init(){ 55 | 56 | namespace bf = boost::filesystem; 57 | 58 | auto db_path = bf::current_path() / db_name_; 59 | 60 | if (bf::exists(db_path)) { 61 | log::info("database")<<"Using "<(newblock.header_.height) 104 | << newblock.header_.hash << static_cast(newblock.header_.difficulty) 105 | << static_cast(newblock.header_.timestamp); 106 | 107 | log::debug("database")<<"chenhao2:"<< newblock.header_.hash; 108 | 109 | cmd.execute(); 110 | xct.commit(); 111 | } 112 | 113 | block chain_database::get_last_block() { 114 | 115 | block cc; 116 | sqlite3pp::query qry(db_conn_, "SELECT height, hash, bits, time_stamp FROM block where height = (SELECT count(*) - 1 FROM block)"); 117 | for (auto i = qry.begin(); i != qry.end(); ++i) { 118 | cc.header_.height = (*i).get(0); 119 | cc.header_.hash = (*i).get(1); 120 | cc.header_.difficulty = (*i).get(2); 121 | cc.header_.timestamp = (*i).get(3); 122 | } 123 | log::info("database")<<"last_block_hash:"<< cc.header_.hash; 124 | 125 | return cc; 126 | } 127 | 128 | uint64_t chain_database::height() { 129 | sqlite3pp::query qry(db_conn_, "SELECT count(*) - 1 FROM block"); 130 | sqlite3pp::query::iterator i = qry.begin(); 131 | return (*i).get(0); 132 | } 133 | 134 | // -------------------- class key_pair_database ------------------ 135 | //使用CryptoPP的RSA库生成新的密钥对 136 | key_pair key_pair_database::get_new_key_pair() { 137 | key_pair key; 138 | log::info("database")<<"getnewkey address:"<< key.address(); 139 | sqlite3pp::transaction xct(db_conn_); 140 | sqlite3pp::command cmd(db_conn_, "INSERT INTO key_pairs (address, private_key) VALUES (?, ?)"); 141 | auto&& keypair = key.encode_pair(); 142 | cmd.binder() << key.address() << keypair.first; 143 | cmd.execute(); 144 | xct.commit(); 145 | return key; 146 | } 147 | 148 | // 从数据库中读取数据 149 | bool key_pair_database::list_keys(Json::Value& root) { 150 | sqlite3pp::query qry(db_conn_, "SELECT private_key FROM key_pairs"); 151 | 152 | for (sqlite3pp::query::iterator i = qry.begin(); i != qry.end(); ++i) { 153 | std::string private_key{(*i).get(0)}; 154 | key_pair each(private_key); 155 | root.append(each.to_json()); 156 | } 157 | return true; 158 | } 159 | 160 | } //tinychain 161 | 162 | -------------------------------------------------------------------------------- /include/sqlite3pp/sqlite3ppext.ipp: -------------------------------------------------------------------------------- 1 | // sqlite3ppext.cpp 2 | // 3 | // The MIT License 4 | // 5 | // Copyright (c) 2015 Wongoo Lee (iwongu at gmail dot com) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | #include 26 | 27 | namespace sqlite3pp 28 | { 29 | namespace ext 30 | { 31 | 32 | namespace 33 | { 34 | 35 | void function_impl(sqlite3_context* ctx, int nargs, sqlite3_value** values) 36 | { 37 | auto f = static_cast(sqlite3_user_data(ctx)); 38 | context c(ctx, nargs, values); 39 | (*f)(c); 40 | } 41 | 42 | void step_impl(sqlite3_context* ctx, int nargs, sqlite3_value** values) 43 | { 44 | auto p = static_cast*>(sqlite3_user_data(ctx)); 45 | auto s = static_cast((*p).first.get()); 46 | context c(ctx, nargs, values); 47 | ((function::function_handler&)*s)(c); 48 | } 49 | 50 | void finalize_impl(sqlite3_context* ctx) 51 | { 52 | auto p = static_cast*>(sqlite3_user_data(ctx)); 53 | auto f = static_cast((*p).second.get()); 54 | context c(ctx); 55 | ((function::function_handler&)*f)(c); 56 | } 57 | 58 | } // namespace 59 | 60 | 61 | inline context::context(sqlite3_context* ctx, int nargs, sqlite3_value** values) 62 | : ctx_(ctx), nargs_(nargs), values_(values) 63 | { 64 | } 65 | 66 | inline int context::args_count() const 67 | { 68 | return nargs_; 69 | } 70 | 71 | inline int context::args_bytes(int idx) const 72 | { 73 | return sqlite3_value_bytes(values_[idx]); 74 | } 75 | 76 | inline int context::args_type(int idx) const 77 | { 78 | return sqlite3_value_type(values_[idx]); 79 | } 80 | 81 | inline int context::get(int idx, int) const 82 | { 83 | return sqlite3_value_int(values_[idx]); 84 | } 85 | 86 | inline double context::get(int idx, double) const 87 | { 88 | return sqlite3_value_double(values_[idx]); 89 | } 90 | 91 | inline long long int context::get(int idx, long long int) const 92 | { 93 | return sqlite3_value_int64(values_[idx]); 94 | } 95 | 96 | inline char const* context::get(int idx, char const*) const 97 | { 98 | return reinterpret_cast(sqlite3_value_text(values_[idx])); 99 | } 100 | 101 | inline std::string context::get(int idx, std::string) const 102 | { 103 | return get(idx, (char const*)0); 104 | } 105 | 106 | inline void const* context::get(int idx, void const*) const 107 | { 108 | return sqlite3_value_blob(values_[idx]); 109 | } 110 | 111 | 112 | 113 | inline void context::result(int value) 114 | { 115 | sqlite3_result_int(ctx_, value); 116 | } 117 | 118 | inline void context::result(double value) 119 | { 120 | sqlite3_result_double(ctx_, value); 121 | } 122 | 123 | inline void context::result(long long int value) 124 | { 125 | sqlite3_result_int64(ctx_, value); 126 | } 127 | 128 | inline void context::result(std::string const& value) 129 | { 130 | result(value.c_str(), false); 131 | } 132 | 133 | inline void context::result(char const* value, bool fcopy) 134 | { 135 | sqlite3_result_text(ctx_, value, std::strlen(value), fcopy ? SQLITE_TRANSIENT : SQLITE_STATIC); 136 | } 137 | 138 | inline void context::result(void const* value, int n, bool fcopy) 139 | { 140 | sqlite3_result_blob(ctx_, value, n, fcopy ? SQLITE_TRANSIENT : SQLITE_STATIC ); 141 | } 142 | 143 | inline void context::result() 144 | { 145 | sqlite3_result_null(ctx_); 146 | } 147 | 148 | inline void context::result(null_type) 149 | { 150 | sqlite3_result_null(ctx_); 151 | } 152 | 153 | inline void context::result_copy(int idx) 154 | { 155 | sqlite3_result_value(ctx_, values_[idx]); 156 | } 157 | 158 | inline void context::result_error(char const* msg) 159 | { 160 | sqlite3_result_error(ctx_, msg, std::strlen(msg)); 161 | } 162 | 163 | inline void* context::aggregate_data(int size) 164 | { 165 | return sqlite3_aggregate_context(ctx_, size); 166 | } 167 | 168 | inline int context::aggregate_count() 169 | { 170 | return sqlite3_aggregate_count(ctx_); 171 | } 172 | 173 | inline function::function(database& db) : db_(db.db_) 174 | { 175 | } 176 | 177 | inline int function::create(char const* name, function_handler h, int nargs) 178 | { 179 | fh_[name] = pfunction_base(new function_handler(h)); 180 | return sqlite3_create_function(db_, name, nargs, SQLITE_UTF8, fh_[name].get(), function_impl, 0, 0); 181 | } 182 | 183 | inline aggregate::aggregate(database& db) : db_(db.db_) 184 | { 185 | } 186 | 187 | inline int aggregate::create(char const* name, function_handler s, function_handler f, int nargs) 188 | { 189 | ah_[name] = std::make_pair(pfunction_base(new function_handler(s)), pfunction_base(new function_handler(f))); 190 | return sqlite3_create_function(db_, name, nargs, SQLITE_UTF8, &ah_[name], 0, step_impl, finalize_impl); 191 | } 192 | 193 | } // namespace ext 194 | 195 | } // namespace sqlite3pp 196 | -------------------------------------------------------------------------------- /include/tinychain/tinychain.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of: 3 | * Comments: 4 | * 5 | **/ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // Encryption Algorithm from cryptopp 18 | #include 19 | #include 20 | #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 //ignore #warning from comipler for MD5 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace tinychain 28 | { 29 | 30 | namespace tc = tinychain; 31 | 32 | // ---------------------------- typedef ---------------------------- 33 | typedef std::string sha256_t; 34 | typedef std::string md5_t; 35 | typedef std::string address_t; 36 | typedef std::string script_sign_t; 37 | typedef std::string script_pubkey_t; 38 | typedef std::string data_t; 39 | typedef CryptoPP::RSA::PublicKey public_key_t; 40 | typedef CryptoPP::RSA::PrivateKey private_key_t; 41 | 42 | // ---------------------------- ulitity ---------------------------- 43 | uint64_t get_now_timestamp(); 44 | sha256_t to_sha256(Json::Value jv); 45 | md5_t to_md5(const std::string& message); 46 | address_t key_to_address(const public_key_t& public_key); 47 | address_t key_to_address(const private_key_t& private_key); 48 | 49 | // ---------------------------- class ---------------------------- 50 | class key_pair 51 | { 52 | 53 | public: 54 | // new key pair 55 | key_pair() { 56 | private_key_.GenerateRandomWithKeySize(rng, 1024); 57 | } 58 | // Copy 59 | key_pair(const key_pair& rk) { 60 | private_key_ = rk.private_key(); 61 | } 62 | // = 63 | key_pair& operator=(const key_pair& rk) { 64 | private_key_ = rk.private_key(); 65 | return *this; 66 | } 67 | 68 | // 从base64直接构造RSA私钥 69 | key_pair(std::string& encoded_prik) { 70 | 71 | log::debug("key_pair-in")< input_item_t; 130 | typedef std::tuple output_item_t; 131 | 132 | typedef std::vector input_t; 133 | typedef std::vector output_t; 134 | 135 | tx() {} 136 | tx(address_t& address); //coinbase 137 | tx(address_t& address, uint64_t amount); 138 | 139 | tx(const tx& rt) { 140 | inputs_ = rt.inputs(); 141 | outputs_ = rt.outputs(); 142 | } 143 | tx& operator=(const tx& rt) { 144 | inputs_ = rt.inputs(); 145 | outputs_ = rt.outputs(); 146 | return *this; 147 | } 148 | tx(tx&&) = default; 149 | tx& operator=(tx&&) = default; 150 | 151 | void print(){ std::cout<<"class tx"< tx_list_t; 172 | 173 | struct blockheader { 174 | uint64_t nonce{0}; 175 | uint64_t height{0}; 176 | uint64_t timestamp{0}; 177 | uint64_t tx_count{0}; 178 | uint64_t difficulty{0}; 179 | sha256_t hash; 180 | sha256_t merkel_root_hash; //TODO 181 | sha256_t prev_hash; 182 | 183 | }; 184 | 185 | 186 | block() {} 187 | block(uint64_t h) {header_.height = h;} 188 | block(const block& rb) { 189 | header_ = rb.header(); 190 | tx_list_ = rb.tx_list(); 191 | } 192 | block& operator=(const block& rb) { 193 | header_ = rb.header(); 194 | tx_list_ = rb.tx_list(); 195 | return *this; 196 | } 197 | 198 | block(block&&) = default; 199 | block& operator=(block&&) = default; 200 | 201 | void print(){ std::cout<<"class block"< 18 | #include //hash 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | namespace mgbubble{ 28 | 29 | thread_local OStream RestServ::out_; 30 | thread_local Tokeniser<'/'> RestServ::uri_; 31 | thread_local int RestServ::state_ = 0; 32 | 33 | void RestServ::reset(HttpMessage& data) noexcept 34 | { 35 | state_ = 0; 36 | 37 | const auto method = data.method(); 38 | if (method == "GET") { 39 | state_ |= MethodGet; 40 | } else if (method == "POST") { 41 | state_ |= MethodPost; 42 | } else if (method == "PUT") { 43 | state_ |= MethodPut; 44 | } else if (method == "DELETE") { 45 | state_ |= MethodDelete; 46 | } 47 | 48 | auto uri = data.uri(); 49 | // Remove leading slash. 50 | if (uri.front() == '/') { 51 | uri.remove_prefix(1); 52 | } 53 | uri_.reset(uri); 54 | } 55 | 56 | void RestServ::httpStatic(mg_connection& nc, HttpMessage data) 57 | { 58 | mg_serve_http(&nc, data.get(), httpoptions_); 59 | } 60 | 61 | void RestServ::websocketBroadcast(mg_connection& nc, const char* msg, size_t len) 62 | { 63 | mg_connection* iter; 64 | 65 | for (iter = mg_next(nc.mgr, nullptr); iter != nullptr; iter = mg_next(nc.mgr, iter)) 66 | { 67 | mg_send_websocket_frame(iter, WEBSOCKET_OP_TEXT, msg, len); 68 | } 69 | } 70 | 71 | void RestServ::websocketSend(mg_connection* nc, const char* msg, size_t len) 72 | { 73 | mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, msg, len); 74 | } 75 | 76 | 77 | // --------------------- websocket interface ----------------------- 78 | void RestServ::websocketSend(mg_connection& nc, WebsocketMessage ws) 79 | { 80 | //process here 81 | std::stringstream sout; 82 | try{ 83 | ws.data_to_arg(); 84 | tinychain::commands cmd{ws.vargv(), node_}; 85 | Json::Value ret; 86 | cmd.exec(ret); 87 | 88 | sout< RestServ::push_session(HttpMessage data) 152 | { 153 | char user[64]{0x00}, pass[64]{0x00}; 154 | auto ul = mg_get_http_var(&(data.get()->body), "user", user, sizeof(user)); 155 | auto pl = mg_get_http_var(&(data.get()->body), "pass", pass, sizeof(pass)); 156 | 157 | auto s = std::make_shared(); 158 | 159 | s->created = s->last_used = mg_time(); 160 | s->user = std::string(user, ul); 161 | s->pass = std::string(pass, pl); 162 | 163 | s->id = std::hash>()(s); 164 | std::string&& seed = std::string(user) + std::to_string(s->id); 165 | s->id = std::hash()(seed); 166 | 167 | session_list_.push_back(s); 168 | 169 | return s; 170 | } 171 | 172 | std::shared_ptr RestServ::get_from_session_list(HttpMessage data) 173 | { 174 | mg_str* cookie_header = mg_get_http_header(data.get(), "cookie");; 175 | if (cookie_header == nullptr) 176 | return nullptr; 177 | 178 | char ssid[32]{0x00}; 179 | if (!mg_http_parse_header(cookie_header, SESSION_COOKIE_NAME, ssid, sizeof(ssid))) 180 | return nullptr; 181 | 182 | auto sid = std::stoul(ssid, nullptr, 10); 183 | 184 | auto ret = std::find_if(session_list_.begin(), session_list_.end(), [&sid](std::shared_ptr p){ 185 | return sid == p->id; 186 | }); 187 | 188 | if (ret == session_list_.end()) 189 | return nullptr; 190 | 191 | (*ret)->last_used = mg_time(); 192 | return *ret; 193 | } 194 | 195 | bool RestServ::remove_from_session_list(HttpMessage data) 196 | { 197 | mg_str* cookie_header = mg_get_http_header(data.get(), "cookie");; 198 | if (cookie_header == nullptr) 199 | return false; 200 | 201 | char ssid[32]{0x00}; 202 | if (!mg_http_parse_header(cookie_header, SESSION_COOKIE_NAME, ssid, sizeof(ssid))) 203 | return false; 204 | 205 | auto sid = std::stoul(ssid, nullptr, 10); 206 | 207 | for (auto iter = session_list_.begin(); iter != session_list_.end(); ++iter) 208 | { 209 | if ( (*iter)->id == sid ) 210 | { 211 | iter = session_list_.erase(iter); 212 | } 213 | } 214 | 215 | return true; 216 | } 217 | 218 | bool RestServ::check_sessions() 219 | { 220 | auto threshold = mg_time() - SESSION_TTL; 221 | 222 | for (auto iter = session_list_.begin(); iter != session_list_.end(); ++iter) 223 | { 224 | if ( (*iter)->last_used < threshold ) 225 | { 226 | iter = session_list_.erase(iter); 227 | } 228 | } 229 | return true; 230 | } 231 | 232 | bool RestServ::user_auth(mg_connection& nc, HttpMessage data) 233 | { 234 | char user[64]{0x00}, pass[64]{0x00}; 235 | auto ul = mg_get_http_var(&(data.get()->body), "user", user, sizeof(user)); 236 | auto pl = mg_get_http_var(&(data.get()->body), "pass", pass, sizeof(pass)); 237 | 238 | try{ 239 | if (ul > 0 && pl > 0){ 240 | //TODO Check valid 241 | }else{ 242 | } 243 | 244 | } catch(std::exception& e){ 245 | out_ << e.what(); 246 | return false; 247 | } 248 | 249 | return true; 250 | } 251 | 252 | }// mgbubble 253 | 254 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/utility/String.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS) - Metaverse. 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under the terms of the 5 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 6 | * License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License along with this program; if 13 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 14 | * 02110-1301, USA. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | /** 27 | * @addtogroup Util 28 | * @{ 29 | */ 30 | 31 | namespace mgbubble { 32 | 33 | constexpr string_view operator""_sv(const char* str, std::size_t len) noexcept 34 | { 35 | return {str, len}; 36 | } 37 | 38 | template 39 | struct StringData { 40 | 41 | // Length in the first cache-line. 42 | std::size_t len; 43 | char buf[MaxN]; 44 | }; 45 | 46 | template 47 | constexpr string_view operator+(const StringData& s) noexcept 48 | { 49 | return {s.buf, s.len}; 50 | } 51 | 52 | /** 53 | * String buffer with fixed upper-bound. 54 | */ 55 | template 56 | class String { 57 | public: 58 | template 59 | String(const String& rhs) noexcept 60 | { 61 | assign(rhs.data(), rhs.size()); 62 | } 63 | String(string_view rhs) noexcept { assign(rhs.data(), rhs.size()); } 64 | String() noexcept { clear(); } 65 | 66 | ~String() noexcept = default; 67 | 68 | // Copy. 69 | String(const String& rhs) noexcept { assign(rhs.data(), rhs.size()); } 70 | constexpr String& operator=(const String& rhs) const noexcept 71 | { 72 | assign(rhs.data(), rhs.size()); 73 | return *this; 74 | } 75 | 76 | // Move. 77 | constexpr String(String&&) noexcept = default; 78 | String& operator=(String&&) noexcept = default; 79 | 80 | template 81 | constexpr String& operator=(const String& rhs) const noexcept 82 | { 83 | assign(rhs.data(), rhs.size()); 84 | return *this; 85 | } 86 | constexpr String& operator=(string_view rhs) const noexcept 87 | { 88 | assign(rhs.data(), rhs.size()); 89 | return *this; 90 | } 91 | template 92 | constexpr int compare(const String& rhs) const noexcept 93 | { 94 | return compare(rhs.data(), rhs.size()); 95 | } 96 | constexpr int compare(string_view rhs) const noexcept 97 | { 98 | return compare(rhs.data(), rhs.size()); 99 | } 100 | constexpr const char* data() const noexcept { return buf_; } 101 | constexpr bool empty() const noexcept { return len_ == 0; } 102 | constexpr size_t size() const noexcept { return len_; } 103 | constexpr void clear() noexcept { len_ = 0; } 104 | 105 | private: 106 | constexpr int compare(const char* rdata, std::size_t rlen) const noexcept 107 | { 108 | int result{std::memcmp(buf_, rdata, std::min(len_, rlen))}; 109 | if (result == 0) { 110 | result = mgbubble::compare(len_, rlen); 111 | } 112 | return result; 113 | } 114 | constexpr void assign(const char* rdata, std::size_t rlen) const noexcept 115 | { 116 | len_ = std::min(MaxN, rlen); 117 | if (len_ > 0) { 118 | std::memcpy(buf_, rdata, len_); 119 | } 120 | } 121 | // Length in the first cache-line. 122 | std::size_t len_; 123 | char buf_[MaxN]; 124 | }; 125 | 126 | template 127 | constexpr string_view operator+(const String& s) noexcept 128 | { 129 | return {s.data(), s.size()}; 130 | } 131 | 132 | template 133 | constexpr bool operator==(const String& lhs, const String& rhs) noexcept 134 | { 135 | return lhs.compare(rhs) == 0; 136 | } 137 | 138 | template 139 | constexpr bool operator==(const String& lhs, string_view rhs) noexcept 140 | { 141 | return lhs.compare(rhs) == 0; 142 | } 143 | 144 | template 145 | constexpr bool operator==(string_view lhs, const String& rhs) noexcept 146 | { 147 | return 0 == rhs.compare(lhs); 148 | } 149 | 150 | template 151 | constexpr bool operator!=(const String& lhs, const String& rhs) noexcept 152 | { 153 | return lhs.compare(rhs) != 0; 154 | } 155 | 156 | template 157 | constexpr bool operator!=(const String& lhs, string_view rhs) noexcept 158 | { 159 | return lhs.compare(rhs) != 0; 160 | } 161 | 162 | template 163 | constexpr bool operator!=(string_view lhs, const String& rhs) noexcept 164 | { 165 | return 0 != rhs.compare(lhs); 166 | } 167 | 168 | template 169 | constexpr bool operator<(const String& lhs, const String& rhs) noexcept 170 | { 171 | return lhs.compare(rhs) < 0; 172 | } 173 | 174 | template 175 | constexpr bool operator<(const String& lhs, string_view rhs) noexcept 176 | { 177 | return lhs.compare(rhs) < 0; 178 | } 179 | 180 | template 181 | constexpr bool operator<(string_view lhs, const String& rhs) noexcept 182 | { 183 | return 0 < rhs.compare(lhs); 184 | } 185 | 186 | template 187 | constexpr bool operator<=(const String& lhs, const String& rhs) noexcept 188 | { 189 | return lhs.compare(rhs) <= 0; 190 | } 191 | 192 | template 193 | constexpr bool operator<=(const String& lhs, string_view rhs) noexcept 194 | { 195 | return lhs.compare(rhs) <= 0; 196 | } 197 | 198 | template 199 | constexpr bool operator<=(string_view lhs, const String& rhs) noexcept 200 | { 201 | return 0 <= rhs.compare(lhs); 202 | } 203 | 204 | template 205 | constexpr bool operator>(const String& lhs, const String& rhs) noexcept 206 | { 207 | return lhs.compare(rhs) > 0; 208 | } 209 | 210 | template 211 | constexpr bool operator>(const String& lhs, string_view rhs) noexcept 212 | { 213 | return lhs.compare(rhs) > 0; 214 | } 215 | 216 | template 217 | constexpr bool operator>(string_view lhs, const String& rhs) noexcept 218 | { 219 | return 0 > rhs.compare(lhs); 220 | } 221 | 222 | template 223 | constexpr bool operator>=(const String& lhs, const String& rhs) noexcept 224 | { 225 | return lhs.compare(rhs) >= 0; 226 | } 227 | 228 | template 229 | constexpr bool operator>=(const String& lhs, string_view rhs) noexcept 230 | { 231 | return lhs.compare(rhs) >= 0; 232 | } 233 | 234 | template 235 | constexpr bool operator>=(string_view lhs, const String& rhs) noexcept 236 | { 237 | return 0 >= rhs.compare(lhs); 238 | } 239 | 240 | template 241 | constexpr std::ostream& operator<<(std::ostream& os, const String& rhs) noexcept 242 | { 243 | return os << +rhs; 244 | } 245 | 246 | template ::value>* = nullptr> 247 | std::string toString(ValueT val) 248 | { 249 | return std::to_string(val); 250 | } 251 | 252 | template ::value>* = nullptr> 253 | std::string toString(const ValueT& val) 254 | { 255 | std::stringstream ss; 256 | ss << val; 257 | return ss.str(); 258 | } 259 | 260 | MVS_API unsigned long stoul(string_view sv) noexcept; 261 | 262 | } // http 263 | 264 | /** @} */ 265 | 266 | -------------------------------------------------------------------------------- /include/sqlite3pp/sqlite3ppext.h: -------------------------------------------------------------------------------- 1 | // sqlite3ppext.h 2 | // 3 | // The MIT License 4 | // 5 | // Copyright (c) 2015 Wongoo Lee (iwongu at gmail dot com) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | #ifndef SQLITE3PPEXT_H 26 | #define SQLITE3PPEXT_H 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "sqlite3pp.h" 36 | 37 | namespace sqlite3pp 38 | { 39 | namespace 40 | { 41 | template 42 | struct Apply { 43 | template 44 | static inline auto apply(F&& f, T&& t, A&&... a) 45 | -> decltype(Apply::apply(std::forward(f), 46 | std::forward(t), 47 | std::get(std::forward(t)), 48 | std::forward(a)...)) 49 | { 50 | return Apply::apply(std::forward(f), 51 | std::forward(t), 52 | std::get(std::forward(t)), 53 | std::forward(a)...); 54 | } 55 | }; 56 | 57 | template<> 58 | struct Apply<0> { 59 | template 60 | static inline auto apply(F&& f, T&&, A&&... a) 61 | -> decltype(std::forward(f)(std::forward(a)...)) 62 | { 63 | return std::forward(f)(std::forward(a)...); 64 | } 65 | }; 66 | 67 | template 68 | inline auto apply(F&& f, T&& t) 69 | -> decltype(Apply::type>::value>::apply(std::forward(f), std::forward(t))) 70 | { 71 | return Apply::type>::value>::apply( 72 | std::forward(f), std::forward(t)); 73 | } 74 | } 75 | 76 | 77 | namespace ext 78 | { 79 | database borrow(sqlite3* pdb) { 80 | return database(pdb); 81 | } 82 | 83 | class context : noncopyable 84 | { 85 | public: 86 | explicit context(sqlite3_context* ctx, int nargs = 0, sqlite3_value** values = nullptr); 87 | 88 | int args_count() const; 89 | int args_bytes(int idx) const; 90 | int args_type(int idx) const; 91 | 92 | template T get(int idx) const { 93 | return get(idx, T()); 94 | } 95 | 96 | void result(int value); 97 | void result(double value); 98 | void result(long long int value); 99 | void result(std::string const& value); 100 | void result(char const* value, bool fcopy); 101 | void result(void const* value, int n, bool fcopy); 102 | void result(); 103 | void result(null_type); 104 | void result_copy(int idx); 105 | void result_error(char const* msg); 106 | 107 | void* aggregate_data(int size); 108 | int aggregate_count(); 109 | 110 | template 111 | std::tuple to_tuple() { 112 | return to_tuple_impl(0, *this, std::tuple()); 113 | } 114 | 115 | private: 116 | int get(int idx, int) const; 117 | double get(int idx, double) const; 118 | long long int get(int idx, long long int) const; 119 | char const* get(int idx, char const*) const; 120 | std::string get(int idx, std::string) const; 121 | void const* get(int idx, void const*) const; 122 | 123 | template 124 | static inline std::tuple to_tuple_impl(int index, const context& c, std::tuple&&) 125 | { 126 | auto h = std::make_tuple(c.context::get(index)); 127 | return std::tuple_cat(h, to_tuple_impl(++index, c, std::tuple())); 128 | } 129 | static inline std::tuple<> to_tuple_impl(int /*index*/, const context& /*c*/, std::tuple<>&&) 130 | { 131 | return std::tuple<>(); 132 | } 133 | 134 | private: 135 | sqlite3_context* ctx_; 136 | int nargs_; 137 | sqlite3_value** values_; 138 | }; 139 | 140 | namespace 141 | { 142 | template 143 | void functionx_impl(sqlite3_context* ctx, int nargs, sqlite3_value** values) 144 | { 145 | context c(ctx, nargs, values); 146 | auto f = static_cast*>(sqlite3_user_data(ctx)); 147 | c.result(apply(*f, c.to_tuple())); 148 | } 149 | } 150 | 151 | class function : noncopyable 152 | { 153 | public: 154 | using function_handler = std::function; 155 | using pfunction_base = std::shared_ptr; 156 | 157 | explicit function(database& db); 158 | 159 | int create(char const* name, function_handler h, int nargs = 0); 160 | 161 | template int create(char const* name, std::function h) { 162 | fh_[name] = std::shared_ptr(new std::function(h)); 163 | return create_function_impl()(db_, fh_[name].get(), name); 164 | } 165 | 166 | private: 167 | 168 | template 169 | struct create_function_impl; 170 | 171 | template 172 | struct create_function_impl 173 | { 174 | int operator()(sqlite3* db, void* fh, char const* name) { 175 | return sqlite3_create_function(db, name, sizeof...(Ps), SQLITE_UTF8, fh, 176 | functionx_impl, 177 | 0, 0); 178 | } 179 | }; 180 | 181 | private: 182 | sqlite3* db_; 183 | 184 | std::map fh_; 185 | }; 186 | 187 | namespace 188 | { 189 | template 190 | void stepx_impl(sqlite3_context* ctx, int nargs, sqlite3_value** values) 191 | { 192 | context c(ctx, nargs, values); 193 | T* t = static_cast(c.aggregate_data(sizeof(T))); 194 | if (c.aggregate_count() == 1) new (t) T; 195 | apply([](T* tt, Ps... ps){tt->step(ps...);}, 196 | std::tuple_cat(std::make_tuple(t), c.to_tuple())); 197 | } 198 | 199 | template 200 | void finishN_impl(sqlite3_context* ctx) 201 | { 202 | context c(ctx); 203 | T* t = static_cast(c.aggregate_data(sizeof(T))); 204 | c.result(t->finish()); 205 | t->~T(); 206 | } 207 | } 208 | 209 | class aggregate : noncopyable 210 | { 211 | public: 212 | using function_handler = std::function; 213 | using pfunction_base = std::shared_ptr; 214 | 215 | explicit aggregate(database& db); 216 | 217 | int create(char const* name, function_handler s, function_handler f, int nargs = 1); 218 | 219 | template 220 | int create(char const* name) { 221 | return sqlite3_create_function(db_, name, sizeof...(Ps), SQLITE_UTF8, 0, 0, stepx_impl, finishN_impl); 222 | } 223 | 224 | private: 225 | sqlite3* db_; 226 | 227 | std::map > ah_; 228 | }; 229 | 230 | } // namespace ext 231 | 232 | } // namespace sqlite3pp 233 | 234 | #include "sqlite3ppext.ipp" 235 | 236 | #endif 237 | -------------------------------------------------------------------------------- /src/lib/logging.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS) 3 | * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS) 4 | * 5 | * This file is part of metaverse. 6 | * 7 | * metaverse is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License with 9 | * additional permissions to the one published by the Free Software 10 | * Foundation, either version 3 of the License, or (at your option) 11 | * any later version. For more information see LICENSE. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace tinychain { 34 | 35 | 36 | log::log(level value, const std::string& domain) 37 | : level_(value), domain_(domain) 38 | { 39 | } 40 | 41 | // g++ bug in initializer list. 42 | // It should be: stream_(std::move(other.stream_)) 43 | // gcc.gnu.org/bugzilla/show_bug.cgi?id=54316 44 | log::log(log&& other) 45 | : level_(other.level_), 46 | domain_(std::move(other.domain_)), 47 | stream_(other.stream_.str()) 48 | { 49 | } 50 | 51 | log::~log() 52 | { 53 | if (destinations_.count(level_) != 0) 54 | destinations_[level_](level_, domain_, stream_.str()); 55 | } 56 | 57 | void log::set_output_function(functor value) 58 | { 59 | destinations_[level_] = value; 60 | } 61 | 62 | void log::clear() 63 | { 64 | destinations_.clear(); 65 | } 66 | 67 | log log::trace(const std::string& domain) 68 | { 69 | return log(level::trace, domain); 70 | } 71 | 72 | log log::debug(const std::string& domain) 73 | { 74 | return log(level::debug, domain); 75 | } 76 | 77 | log log::info(const std::string& domain) 78 | { 79 | return log(level::info, domain); 80 | } 81 | 82 | log log::warning(const std::string& domain) 83 | { 84 | return log(level::warning, domain); 85 | } 86 | 87 | log log::error(const std::string& domain) 88 | { 89 | return log(level::error, domain); 90 | } 91 | 92 | log log::fatal(const std::string& domain) 93 | { 94 | return log(level::fatal, domain); 95 | } 96 | 97 | std::string log::to_text(level value) 98 | { 99 | switch (value) 100 | { 101 | case level::trace: 102 | return "TRACE"; 103 | case level::debug: 104 | return "DEBUG"; 105 | case level::info: 106 | return "INFO"; 107 | case level::warning: 108 | return "WARNING"; 109 | case level::error: 110 | return "ERROR"; 111 | case level::fatal: 112 | return "FATAL"; 113 | case level::null: 114 | return "NULL"; 115 | default: 116 | return ""; 117 | } 118 | } 119 | 120 | void log::to_stream(std::ostream& out, level value, const std::string& domain, 121 | const std::string& body) 122 | { 123 | std::ostringstream buffer; 124 | buffer << to_text(value); 125 | if (!domain.empty()) 126 | buffer << " [" << domain << "]"; 127 | 128 | buffer << ": " << body << std::endl; 129 | 130 | // Buffering prevents line interleaving across threads. 131 | out << buffer.str(); 132 | out.flush(); 133 | } 134 | 135 | void log::output_ignore(level, const std::string&, const std::string&) 136 | { 137 | } 138 | 139 | void log::output_cout(level value, const std::string& domain, 140 | const std::string& body) 141 | { 142 | to_stream(std::cout, value, domain, body); 143 | } 144 | 145 | void log::output_cerr(level value, const std::string& domain, 146 | const std::string& body) 147 | { 148 | to_stream(std::cerr, value, domain, body); 149 | } 150 | 151 | log::destinations log::destinations_ 152 | { 153 | #ifdef NDEBUG 154 | std::make_pair(level::trace, output_ignore), 155 | std::make_pair(level::debug, output_ignore), 156 | #else 157 | std::make_pair(level::trace, output_cout), 158 | std::make_pair(level::debug, output_cout), 159 | #endif 160 | std::make_pair(level::info, output_cout), 161 | std::make_pair(level::warning, output_cerr), 162 | std::make_pair(level::error, output_cerr), 163 | std::make_pair(level::fatal, output_cerr) 164 | }; 165 | 166 | //////////////////////////////log above/////////////////////////////////////////////// 167 | 168 | // Guard against concurrent console writes. 169 | static std::mutex console_mutex; 170 | 171 | // Guard against concurrent file writes. 172 | static std::mutex file_mutex; 173 | 174 | template 175 | // TODO:limit template type of instance 176 | // class = typename std::enable_if::value>::type> 177 | static inline void do_logging(T& ofs, log::level level, const std::string& domain, 178 | const std::string& body) 179 | { 180 | if (body.empty()) 181 | { 182 | return; 183 | } 184 | 185 | namespace ptime = boost::posix_time; 186 | 187 | static const auto form = "%1% %2% [%3%] %4%\n"; 188 | const auto message = boost::format(form) % 189 | ptime::to_iso_string(ptime::second_clock::local_time()) % 190 | log::to_text(level) % 191 | domain % 192 | body; 193 | 194 | { 195 | // Critical Section 196 | /////////////////////////////////////////////////////////////////////// 197 | std::unique_lock lock_file(file_mutex); 198 | ofs << message; 199 | 200 | #if 0 201 | // Cut up log file if over max_size 202 | if (std::is_same::value) 203 | { 204 | std::ofstream& bo = dynamic_cast(ofs); 205 | auto& current_size = bo.current_size(); 206 | current_size += message.size(); 207 | if (bo.current_size() > bo.max_size()) 208 | { 209 | bo.close(); 210 | bo.open(bo.path(), std::ios::trunc | std::ios::out); 211 | current_size = 0; 212 | } 213 | } 214 | #endif 215 | ofs.flush(); 216 | /////////////////////////////////////////////////////////////////////// 217 | 218 | } 219 | 220 | } 221 | 222 | static void output_ignore(std::ofstream& file, log::level level, 223 | const std::string& domain, const std::string& body) 224 | { 225 | 226 | } 227 | 228 | static void output_file(std::ofstream& file, log::level level, 229 | const std::string& domain, const std::string& body) 230 | { 231 | do_logging(file, level, domain, body); 232 | } 233 | 234 | static void output_both(std::ofstream& file, std::ostream& output, 235 | log::level level, const std::string& domain, const std::string& body) 236 | { 237 | do_logging(file, level, domain, body); 238 | do_logging(output, level, domain, body); 239 | } 240 | 241 | static void error_file(std::ofstream& file, log::level level, 242 | const std::string& domain, const std::string& body) 243 | { 244 | do_logging(file, level, domain, body); 245 | } 246 | 247 | static void error_both(std::ofstream& file, std::ostream& error, 248 | log::level level, const std::string& domain, const std::string& body) 249 | { 250 | do_logging(file, level, domain, body); 251 | do_logging(error, level, domain, body); 252 | } 253 | 254 | void initialize_logging(std::ofstream& debug, std::ofstream& error, 255 | std::ostream& output_stream, std::ostream& error_stream, 256 | std::string level) 257 | { 258 | using namespace std::placeholders; 259 | 260 | auto debug_log_level = log::level::debug; 261 | if (level == "INFO" || level == "info") 262 | debug_log_level = log::level::info; 263 | else if (level == "TRACE" || level == "trace") 264 | debug_log_level = log::level::trace; 265 | 266 | // setup log level for debug_log 267 | if (debug_log_level < log::level::debug) 268 | { 269 | // trace|debug|info => debug_log 270 | log::trace("").set_output_function(std::bind(output_file, 271 | std::ref(debug), _1, _2, _3)); 272 | log::debug("").set_output_function(std::bind(output_file, 273 | std::ref(debug), _1, _2, _3)); 274 | } 275 | else if (debug_log_level debug_log 280 | log::debug("").set_output_function(std::bind(output_file, 281 | std::ref(debug), _1, _2, _3)); 282 | } 283 | else if (debug_log_level debug_log 286 | log::trace("").set_output_function(std::bind(output_ignore, 287 | std::ref(debug), _1, _2, _3)); 288 | log::debug("").set_output_function(std::bind(output_ignore, 289 | std::ref(debug), _1, _2, _3)); 290 | } 291 | 292 | // info => debug_log + console 293 | log::info("").set_output_function(std::bind(output_both, 294 | std::ref(debug), std::ref(output_stream), _1, _2, _3)); 295 | // warning|error|fatal => error_log + console 296 | log::warning("").set_output_function(std::bind(error_file, 297 | std::ref(error), _1, _2, _3)); 298 | log::error("").set_output_function(std::bind(error_both, 299 | std::ref(error), std::ref(error_stream), _1, _2, _3)); 300 | log::fatal("").set_output_function(std::bind(error_both, 301 | std::ref(error), std::ref(error_stream), _1, _2, _3)); 302 | } 303 | 304 | } // namespace tinychain 305 | -------------------------------------------------------------------------------- /include/sqlite3pp/sqlite3pp.h: -------------------------------------------------------------------------------- 1 | // sqlite3pp.h 2 | // 3 | // The MIT License 4 | // 5 | // Copyright (c) 2015 Wongoo Lee (iwongu at gmail dot com) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | #ifndef SQLITE3PP_H 26 | #define SQLITE3PP_H 27 | 28 | #define SQLITE3PP_VERSION "1.0.8" 29 | #define SQLITE3PP_VERSION_MAJOR 1 30 | #define SQLITE3PP_VERSION_MINOR 0 31 | #define SQLITE3PP_VERSION_PATCH 8 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #ifdef SQLITE3PP_LOADABLE_EXTENSION 40 | #include 41 | SQLITE_EXTENSION_INIT1 42 | #else 43 | # include 44 | #endif 45 | 46 | namespace sqlite3pp 47 | { 48 | class database; 49 | 50 | namespace ext 51 | { 52 | class function; 53 | class aggregate; 54 | database borrow(sqlite3* pdb); 55 | } 56 | 57 | template 58 | struct convert { 59 | using to_int = int; 60 | }; 61 | 62 | class null_type {}; 63 | 64 | class noncopyable 65 | { 66 | protected: 67 | noncopyable() = default; 68 | ~noncopyable() = default; 69 | 70 | noncopyable(noncopyable&&) = default; 71 | noncopyable& operator=(noncopyable&&) = default; 72 | 73 | noncopyable(noncopyable const&) = delete; 74 | noncopyable& operator=(noncopyable const&) = delete; 75 | }; 76 | 77 | class database : noncopyable 78 | { 79 | friend class statement; 80 | friend class database_error; 81 | friend class ext::function; 82 | friend class ext::aggregate; 83 | friend database ext::borrow(sqlite3* pdb); 84 | 85 | public: 86 | using busy_handler = std::function; 87 | using commit_handler = std::function; 88 | using rollback_handler = std::function; 89 | using update_handler = std::function; 90 | using authorize_handler = std::function; 91 | using backup_handler = std::function; 92 | 93 | explicit database(char const* dbname = nullptr, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, const char* vfs = nullptr); 94 | 95 | database(database&& db); 96 | database& operator=(database&& db); 97 | 98 | ~database(); 99 | 100 | int connect(char const* dbname, int flags, const char* vfs = nullptr); 101 | int disconnect(); 102 | 103 | int attach(char const* dbname, char const* name); 104 | int detach(char const* name); 105 | 106 | int backup(database& destdb, backup_handler h = {}); 107 | int backup(char const* dbname, database& destdb, char const* destdbname, backup_handler h, int step_page = 5); 108 | 109 | long long int last_insert_rowid() const; 110 | 111 | int enable_foreign_keys(bool enable = true); 112 | int enable_triggers(bool enable = true); 113 | int enable_extended_result_codes(bool enable = true); 114 | 115 | int changes() const; 116 | 117 | int error_code() const; 118 | int extended_error_code() const; 119 | char const* error_msg() const; 120 | 121 | int execute(char const* sql); 122 | int executef(char const* sql, ...); 123 | 124 | int set_busy_timeout(int ms); 125 | 126 | void set_busy_handler(busy_handler h); 127 | void set_commit_handler(commit_handler h); 128 | void set_rollback_handler(rollback_handler h); 129 | void set_update_handler(update_handler h); 130 | void set_authorize_handler(authorize_handler h); 131 | 132 | private: 133 | database(sqlite3* pdb) : db_(pdb), borrowing_(true) {} 134 | 135 | private: 136 | sqlite3* db_; 137 | bool borrowing_; 138 | 139 | busy_handler bh_; 140 | commit_handler ch_; 141 | rollback_handler rh_; 142 | update_handler uh_; 143 | authorize_handler ah_; 144 | }; 145 | 146 | class database_error : public std::runtime_error 147 | { 148 | public: 149 | explicit database_error(char const* msg); 150 | explicit database_error(database& db); 151 | }; 152 | 153 | enum copy_semantic { copy, nocopy }; 154 | 155 | class statement : noncopyable 156 | { 157 | public: 158 | int prepare(char const* stmt); 159 | int finish(); 160 | 161 | int bind(int idx, int value); 162 | int bind(int idx, double value); 163 | int bind(int idx, long long int value); 164 | int bind(int idx, char const* value, copy_semantic fcopy); 165 | int bind(int idx, void const* value, int n, copy_semantic fcopy); 166 | int bind(int idx, std::string const& value, copy_semantic fcopy); 167 | int bind(int idx); 168 | int bind(int idx, null_type); 169 | 170 | int bind(char const* name, int value); 171 | int bind(char const* name, double value); 172 | int bind(char const* name, long long int value); 173 | int bind(char const* name, char const* value, copy_semantic fcopy); 174 | int bind(char const* name, void const* value, int n, copy_semantic fcopy); 175 | int bind(char const* name, std::string const& value, copy_semantic fcopy); 176 | int bind(char const* name); 177 | int bind(char const* name, null_type); 178 | 179 | int step(); 180 | int reset(); 181 | 182 | protected: 183 | explicit statement(database& db, char const* stmt = nullptr); 184 | ~statement(); 185 | 186 | int prepare_impl(char const* stmt); 187 | int finish_impl(sqlite3_stmt* stmt); 188 | 189 | protected: 190 | database& db_; 191 | sqlite3_stmt* stmt_; 192 | char const* tail_; 193 | }; 194 | 195 | class command : public statement 196 | { 197 | public: 198 | class bindstream 199 | { 200 | public: 201 | bindstream(command& cmd, int idx); 202 | 203 | template 204 | bindstream& operator << (T value) { 205 | auto rc = cmd_.bind(idx_, value); 206 | if (rc != SQLITE_OK) { 207 | throw database_error(cmd_.db_); 208 | } 209 | ++idx_; 210 | return *this; 211 | } 212 | bindstream& operator << (char const* value) { 213 | auto rc = cmd_.bind(idx_, value, copy); 214 | if (rc != SQLITE_OK) { 215 | throw database_error(cmd_.db_); 216 | } 217 | ++idx_; 218 | return *this; 219 | } 220 | bindstream& operator << (std::string const& value) { 221 | auto rc = cmd_.bind(idx_, value, copy); 222 | if (rc != SQLITE_OK) { 223 | throw database_error(cmd_.db_); 224 | } 225 | ++idx_; 226 | return *this; 227 | } 228 | 229 | private: 230 | command& cmd_; 231 | int idx_; 232 | }; 233 | 234 | explicit command(database& db, char const* stmt = nullptr); 235 | 236 | bindstream binder(int idx = 1); 237 | 238 | int execute(); 239 | int execute_all(); 240 | }; 241 | 242 | class query : public statement 243 | { 244 | public: 245 | class rows 246 | { 247 | public: 248 | class getstream 249 | { 250 | public: 251 | getstream(rows* rws, int idx); 252 | 253 | template 254 | getstream& operator >> (T& value) { 255 | value = rws_->get(idx_, T()); 256 | ++idx_; 257 | return *this; 258 | } 259 | 260 | private: 261 | rows* rws_; 262 | int idx_; 263 | }; 264 | 265 | explicit rows(sqlite3_stmt* stmt); 266 | 267 | int data_count() const; 268 | int column_type(int idx) const; 269 | 270 | int column_bytes(int idx) const; 271 | 272 | template T get(int idx) const { 273 | return get(idx, T()); 274 | } 275 | 276 | template 277 | std::tuple get_columns(typename convert::to_int... idxs) const { 278 | return std::make_tuple(get(idxs, Ts())...); 279 | } 280 | 281 | getstream getter(int idx = 0); 282 | 283 | private: 284 | int get(int idx, int) const; 285 | double get(int idx, double) const; 286 | long long int get(int idx, long long int) const; 287 | char const* get(int idx, char const*) const; 288 | std::string get(int idx, std::string) const; 289 | void const* get(int idx, void const*) const; 290 | null_type get(int idx, null_type) const; 291 | 292 | private: 293 | sqlite3_stmt* stmt_; 294 | }; 295 | 296 | class query_iterator 297 | : public std::iterator 298 | { 299 | public: 300 | query_iterator(); 301 | explicit query_iterator(query* cmd); 302 | 303 | bool operator==(query_iterator const&) const; 304 | bool operator!=(query_iterator const&) const; 305 | 306 | query_iterator& operator++(); 307 | 308 | value_type operator*() const; 309 | 310 | private: 311 | query* cmd_; 312 | int rc_; 313 | }; 314 | 315 | explicit query(database& db, char const* stmt = nullptr); 316 | 317 | int column_count() const; 318 | 319 | char const* column_name(int idx) const; 320 | char const* column_decltype(int idx) const; 321 | 322 | using iterator = query_iterator; 323 | 324 | iterator begin(); 325 | iterator end(); 326 | }; 327 | 328 | class transaction : noncopyable 329 | { 330 | public: 331 | explicit transaction(database& db, bool fcommit = false, bool freserve = false); 332 | ~transaction(); 333 | 334 | int commit(); 335 | int rollback(); 336 | 337 | private: 338 | database* db_; 339 | bool fcommit_; 340 | }; 341 | 342 | } // namespace sqlite3pp 343 | 344 | #include "sqlite3pp.ipp" 345 | 346 | #endif 347 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/Mongoose.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS). 3 | * Copyright (C) 2013, 2016 Swirly Cloud Limited. 4 | * 5 | * This program is free software; you can redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 10 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program; if 14 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | #ifndef MVSD_MONGOOSE_HPP 18 | #define MVSD_MONGOOSE_HPP 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "mongoose/mongoose.h" 25 | /** 26 | * @addtogroup Web 27 | * @{ 28 | */ 29 | 30 | namespace mgbubble { 31 | 32 | #define SESSION_COOKIE_NAME "2iBXdhW9rQxbnDdNQk9KdjiytM9X" 33 | 34 | inline string_view operator+(const mg_str& str) noexcept 35 | { 36 | return {str.p, str.len}; 37 | } 38 | 39 | inline string_view operator+(const websocket_message& msg) noexcept 40 | { 41 | return {reinterpret_cast(msg.data), msg.size}; 42 | } 43 | 44 | class ToCommandArg{ 45 | public: 46 | auto argv() const noexcept { return argv_; } 47 | auto argc() const noexcept { return argc_; } 48 | const auto& vargv() const noexcept { return vargv_; } 49 | const auto& get_command() const { 50 | if(!vargv_.empty()) 51 | return vargv_[0]; 52 | throw std::logic_error{"no command found"}; 53 | } 54 | void add_arg(std::string&& outside); 55 | 56 | static const int max_paramters{32}; 57 | protected: 58 | 59 | virtual void data_to_arg() = 0; 60 | const char* argv_[max_paramters]{nullptr}; 61 | int argc_{0}; 62 | 63 | std::vector vargv_; 64 | }; 65 | 66 | 67 | class HttpMessage : public ToCommandArg{ 68 | public: 69 | HttpMessage(http_message* impl) noexcept : impl_{impl} {} 70 | ~HttpMessage() noexcept = default; 71 | 72 | // Copy. 73 | // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1778 74 | HttpMessage(const HttpMessage&) = default; 75 | HttpMessage& operator=(const HttpMessage&) = default; 76 | 77 | // Move. 78 | HttpMessage(HttpMessage&&) = default; 79 | HttpMessage& operator=(HttpMessage&&) = default; 80 | 81 | auto get() const noexcept { return impl_; } 82 | auto method() const noexcept { return +impl_->method; } 83 | auto uri() const noexcept { return +impl_->uri; } 84 | auto proto() const noexcept { return +impl_->proto; } 85 | auto queryString() const noexcept { return +impl_->query_string; } 86 | auto header(const char* name) const noexcept 87 | { 88 | auto* val = mg_get_http_header(impl_, name); 89 | return val ? +*val : string_view{}; 90 | } 91 | auto body() const noexcept { return +impl_->body; } 92 | 93 | void data_to_arg() override; 94 | 95 | private: 96 | 97 | http_message* impl_; 98 | }; 99 | 100 | class WebsocketMessage:public ToCommandArg { // connect to bx command-tool 101 | public: 102 | WebsocketMessage(websocket_message* impl) noexcept : impl_{impl} {} 103 | ~WebsocketMessage() noexcept = default; 104 | 105 | // Copy. 106 | WebsocketMessage(const WebsocketMessage&) = default; 107 | WebsocketMessage& operator=(const WebsocketMessage&) = default; 108 | 109 | // Move. 110 | WebsocketMessage(WebsocketMessage&&) = default; 111 | WebsocketMessage& operator=(WebsocketMessage&&) = default; 112 | 113 | auto get() const noexcept { return impl_; } 114 | auto data() const noexcept { return reinterpret_cast(impl_->data); } 115 | auto size() const noexcept { return impl_->size; } 116 | 117 | void data_to_arg() override; 118 | private: 119 | websocket_message* impl_; 120 | }; 121 | 122 | struct Session{ 123 | Session() = default; 124 | Session(uint64_t a1, double a2, double a3, 125 | std::string&& a4, std::string a5): 126 | id(a1), created(a2), last_used(a3), user(a4), pass(a5){} 127 | ~Session() = default; 128 | 129 | uint64_t id; 130 | double created; 131 | double last_used; 132 | std::string user; 133 | std::string pass; 134 | }; 135 | 136 | template 137 | class Mgr { 138 | public: 139 | // Copy. 140 | Mgr(const Mgr&) = delete; 141 | Mgr& operator=(const Mgr&) = delete; 142 | 143 | // Move. 144 | Mgr(Mgr&&) = delete; 145 | Mgr& operator=(Mgr&&) = delete; 146 | 147 | mg_connection& bind(const char* addr) 148 | { 149 | #if MG_ENABLE_MUTITHREADS 150 | auto* conn = mg_bind(&mgr_, addr, handler_mt); 151 | #else 152 | auto* conn = mg_bind(&mgr_, addr, handler); 153 | #endif 154 | if (!conn) 155 | throw Error{"mg_bind() failed"}; 156 | conn->user_data = this; 157 | return *conn; 158 | } 159 | time_t poll(int milli) { return mg_mgr_poll(&mgr_, milli); } 160 | 161 | // session control 162 | static void login_handler(mg_connection* conn, int ev, void* data){ 163 | http_message* hm = static_cast(data); 164 | auto* self = static_cast(conn->user_data); 165 | 166 | if (mg_vcmp(&hm->method, "POST") != 0) { 167 | mg_serve_http(conn, hm, self->get_httpoptions()); 168 | }else{ 169 | if ( self->user_auth(*conn, hm) ){ 170 | std::ostringstream shead; 171 | auto ret = self->push_session(hm); 172 | shead<<"Set-Cookie: " SESSION_COOKIE_NAME "="<id<<"; path=/"; 173 | mg_http_send_redirect(conn, 302, mg_mk_str("/"), mg_mk_str(shead.str().c_str())); 174 | } 175 | } 176 | conn->flags |= MG_F_SEND_AND_CLOSE; 177 | } 178 | 179 | static void logout_handler(mg_connection* conn, int ev, void* data){ 180 | http_message* hm = static_cast(data); 181 | auto* self = static_cast(conn->user_data); 182 | 183 | std::ostringstream shead; 184 | shead<<"Set-Cookie: " SESSION_COOKIE_NAME "="; 185 | mg_http_send_redirect(conn, 302, mg_mk_str("/login.html"), mg_mk_str(shead.str().c_str())); 186 | self->remove_from_session_list(hm); 187 | 188 | conn->flags |= MG_F_SEND_AND_CLOSE; 189 | } 190 | 191 | constexpr static const double session_check_interval = 5.0; 192 | static const int thread_num_ = 2; 193 | 194 | protected: 195 | Mgr() noexcept { 196 | mg_mgr_init(&mgr_, this); 197 | #if MG_ENABLE_MUTITHREADS 198 | start(); 199 | #endif 200 | } 201 | ~Mgr() noexcept { mg_mgr_free(&mgr_); } 202 | 203 | private: 204 | 205 | #if MG_ENABLE_MUTITHREADS 206 | void start(){ 207 | for (int i=0; i < thread_num_; i++) { 208 | std::thread th([this, i]{ 209 | mg_mgr& mg = child_mgrs_[i]; 210 | mg_mgr_init(&mg, this); 211 | 212 | mg_socketpair(mg.mthread_ctl, SOCK_STREAM); 213 | 214 | Queue &queue = queue_connections[i]; 215 | 216 | while(1) { 217 | while(1){ 218 | mg_connection* conn = NULL; 219 | if(queue.pop(conn) == false){ 220 | break; 221 | } 222 | conn->handler = handler; 223 | mg_add_conn(&mg, conn); 224 | } 225 | 226 | mg_mgr_poll(&mg, 100); 227 | } 228 | }); 229 | th.detach(); 230 | } 231 | } 232 | 233 | static void handler_mt(mg_connection* conn, int event, void* data) 234 | { 235 | if(event == MG_EV_ACCEPT) { 236 | if(conn) { 237 | mg_remove_conn(conn); 238 | int index = conn->sock % thread_num_; 239 | queue_connections[index].push(conn); 240 | MG_SEND_FUNC(child_mgrs_[index].mthread_ctl[1], "a", 1, 0); 241 | } 242 | } 243 | } 244 | #endif 245 | 246 | static void handler(mg_connection* conn, int event, void* data) 247 | { 248 | http_message* hm = static_cast(data); 249 | websocket_message* ws = static_cast(data); 250 | auto* self = static_cast(conn->user_data); 251 | 252 | switch (event) { 253 | case MG_EV_CLOSE:{ 254 | if (conn->flags & MG_F_IS_WEBSOCKET) { 255 | //self->websocketBroadcast(*conn, "left", 4); 256 | }else{ 257 | conn->user_data = nullptr; 258 | } 259 | break; 260 | } 261 | case MG_EV_HTTP_REQUEST:{ 262 | 263 | // rpc call 264 | if (mg_ncasecmp((&hm->uri)->p, "/rpc", 4u) == 0){ 265 | self->httpRpcRequest(*conn, hm); 266 | break; 267 | }else{ 268 | self->httpStatic(*conn, hm); 269 | conn->flags |= MG_F_SEND_AND_CLOSE; 270 | break; 271 | } 272 | } 273 | case MG_EV_WEBSOCKET_HANDSHAKE_DONE:{ 274 | self->websocketSend(conn, "connected", 9); 275 | break; 276 | } 277 | case MG_EV_WEBSOCKET_FRAME:{ 278 | self->websocketSend(*conn, ws); 279 | break; 280 | } 281 | case MG_EV_SSI_CALL:{ 282 | } 283 | case MG_EV_TIMER:{ 284 | self->check_sessions(); 285 | mg_set_timer(conn, mg_time() + session_check_interval); 286 | break; 287 | } 288 | }// switch 289 | }// handler 290 | 291 | mg_mgr mgr_; 292 | #if MG_ENABLE_MUTITHREADS 293 | static Queue queue_connections[thread_num_]; 294 | static mg_mgr child_mgrs_[thread_num_]; 295 | #endif 296 | }; 297 | 298 | #if MG_ENABLE_MUTITHREADS 299 | template 300 | Queue Mgr::queue_connections[thread_num_]; 301 | 302 | template 303 | mg_mgr Mgr::child_mgrs_[thread_num_]; 304 | #endif 305 | 306 | } // http 307 | 308 | /** @} */ 309 | 310 | #endif // MVSD_MONGOOSE_HPP 311 | -------------------------------------------------------------------------------- /include/metaverse/mgbubble/exception/Instances.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS). 3 | * Copyright (C) 2013, 2016 Swirly Cloud Limited. 4 | * 5 | * This program is free software; you can redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 10 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program; if 14 | * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | 23 | /** 24 | * @addtogroup Exception 25 | * @{ 26 | */ 27 | 28 | namespace mgbubble { 29 | 30 | class MVS_API ServException : public Exception { 31 | public: 32 | explicit ServException(string_view what) noexcept : Exception{what} {} 33 | ~ServException() noexcept override; 34 | 35 | // Copy. 36 | ServException(const ServException&) noexcept = default; 37 | ServException& operator=(const ServException&) noexcept = default; 38 | 39 | // Move. 40 | ServException(ServException&&) noexcept = default; 41 | ServException& operator=(ServException&&) noexcept = default; 42 | 43 | static void toJson(int status, const char* reason, const char* detail, std::ostream& os); 44 | 45 | void toJson(std::ostream& os) const { toJson(httpStatus(), httpReason(), what(), os); } 46 | 47 | virtual int httpStatus() const noexcept = 0; 48 | 49 | virtual const char* httpReason() const noexcept = 0; 50 | }; 51 | 52 | inline std::ostream& operator<<(std::ostream& os, const ServException& e) 53 | { 54 | e.toJson(os); 55 | return os; 56 | } 57 | 58 | /** 59 | * The request could not be understood by the server due to malformed syntax. The client SHOULD NOT 60 | * repeat the request without modifications. 61 | */ 62 | class MVS_API BadRequestException : public ServException { 63 | public: 64 | explicit BadRequestException(string_view what) noexcept : ServException{what} {} 65 | ~BadRequestException() noexcept override; 66 | 67 | // Copy. 68 | BadRequestException(const BadRequestException&) noexcept = default; 69 | BadRequestException& operator=(const BadRequestException&) noexcept = default; 70 | 71 | // Move. 72 | BadRequestException(BadRequestException&&) noexcept = default; 73 | BadRequestException& operator=(BadRequestException&&) noexcept = default; 74 | 75 | int httpStatus() const noexcept override; 76 | 77 | const char* httpReason() const noexcept override; 78 | }; 79 | 80 | class MVS_API AlreadyExistsException : public BadRequestException { 81 | public: 82 | explicit AlreadyExistsException(string_view what) noexcept : BadRequestException{what} {} 83 | ~AlreadyExistsException() noexcept override; 84 | 85 | // Copy. 86 | AlreadyExistsException(const AlreadyExistsException&) noexcept = default; 87 | AlreadyExistsException& operator=(const AlreadyExistsException&) noexcept = default; 88 | 89 | // Move. 90 | AlreadyExistsException(AlreadyExistsException&&) noexcept = default; 91 | AlreadyExistsException& operator=(AlreadyExistsException&&) noexcept = default; 92 | }; 93 | 94 | class MVS_API RefAlreadyExistsException : public AlreadyExistsException { 95 | public: 96 | explicit RefAlreadyExistsException(string_view what) noexcept : AlreadyExistsException{what} 97 | { 98 | } 99 | RefAlreadyExistsException() noexcept = default; 100 | 101 | ~RefAlreadyExistsException() noexcept override; 102 | 103 | // Copy. 104 | RefAlreadyExistsException(const RefAlreadyExistsException&) noexcept = default; 105 | RefAlreadyExistsException& operator=(const RefAlreadyExistsException&) noexcept = default; 106 | 107 | // Move. 108 | RefAlreadyExistsException(RefAlreadyExistsException&&) noexcept = default; 109 | RefAlreadyExistsException& operator=(RefAlreadyExistsException&&) noexcept = default; 110 | }; 111 | 112 | class MVS_API InvalidException : public BadRequestException { 113 | public: 114 | explicit InvalidException(string_view what) noexcept : BadRequestException{what} {} 115 | ~InvalidException() noexcept override; 116 | 117 | // Copy. 118 | InvalidException(const InvalidException&) noexcept = default; 119 | InvalidException& operator=(const InvalidException&) noexcept = default; 120 | 121 | // Move. 122 | InvalidException(InvalidException&&) noexcept = default; 123 | InvalidException& operator=(InvalidException&&) noexcept = default; 124 | }; 125 | 126 | /** 127 | * The server understood the request, but is refusing to fulfill it. Authorization will not help and 128 | * the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to 129 | * make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal 130 | * in the entity. If the server does not wish to make this information available to the client, the 131 | * status code 404 (Not Found) can be used instead. 132 | */ 133 | class MVS_API ForbiddenException : public ServException { 134 | public: 135 | explicit ForbiddenException(string_view what) noexcept : ServException{what} {} 136 | ~ForbiddenException() noexcept override; 137 | 138 | // Copy. 139 | ForbiddenException(const ForbiddenException&) noexcept = default; 140 | ForbiddenException& operator=(const ForbiddenException&) noexcept = default; 141 | 142 | // Move. 143 | ForbiddenException(ForbiddenException&&) noexcept = default; 144 | ForbiddenException& operator=(ForbiddenException&&) noexcept = default; 145 | 146 | int httpStatus() const noexcept override; 147 | 148 | const char* httpReason() const noexcept override; 149 | }; 150 | 151 | /** 152 | * The server encountered an unexpected condition which prevented it from fulfilling the request. 153 | */ 154 | class MVS_API InternalException : public ServException { 155 | public: 156 | explicit InternalException(string_view what) noexcept : ServException{what} {} 157 | ~InternalException() noexcept override; 158 | 159 | // Copy. 160 | InternalException(const InternalException&) noexcept = default; 161 | InternalException& operator=(const InternalException&) noexcept = default; 162 | 163 | // Move. 164 | InternalException(InternalException&&) noexcept = default; 165 | InternalException& operator=(InternalException&&) noexcept = default; 166 | 167 | int httpStatus() const noexcept override; 168 | 169 | const char* httpReason() const noexcept override; 170 | }; 171 | 172 | /** 173 | * The method specified in the Request-Line is not allowed for the resource identified by the 174 | * Request-URI. The response MUST include an Allow header containing a list of valid methods for the 175 | * requested resource. 176 | */ 177 | class MVS_API MethodNotAllowedException : public ServException { 178 | public: 179 | explicit MethodNotAllowedException(string_view what) noexcept : ServException{what} {} 180 | ~MethodNotAllowedException() noexcept override; 181 | 182 | // Copy. 183 | MethodNotAllowedException(const MethodNotAllowedException&) noexcept = default; 184 | MethodNotAllowedException& operator=(const MethodNotAllowedException&) noexcept = default; 185 | 186 | // Move. 187 | MethodNotAllowedException(MethodNotAllowedException&&) noexcept = default; 188 | MethodNotAllowedException& operator=(MethodNotAllowedException&&) noexcept = default; 189 | 190 | int httpStatus() const noexcept override; 191 | 192 | const char* httpReason() const noexcept override; 193 | }; 194 | 195 | /** 196 | * The server has not found anything matching the Request-URI. No indication is given of whether the 197 | * condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server 198 | * knows, through some internally configurable mechanism, that an old resource is permanently 199 | * unavailable and has no forwarding address. This status code is commonly used when the server does 200 | * not wish to reveal exactly why the request has been refused, or when no other response is 201 | * applicable. 202 | */ 203 | class MVS_API NotFoundException : public ServException { 204 | public: 205 | explicit NotFoundException(string_view what) noexcept : ServException{what} {} 206 | ~NotFoundException() noexcept override; 207 | 208 | // Copy. 209 | NotFoundException(const NotFoundException&) noexcept = default; 210 | NotFoundException& operator=(const NotFoundException&) noexcept = default; 211 | 212 | // Move. 213 | NotFoundException(NotFoundException&&) noexcept = default; 214 | NotFoundException& operator=(NotFoundException&&) noexcept = default; 215 | 216 | int httpStatus() const noexcept override; 217 | 218 | const char* httpReason() const noexcept override; 219 | }; 220 | 221 | /** 222 | * The server is currently unable to handle the request due to a temporary overloading or 223 | * maintenance of the server. The implication is that this is a temporary condition which will be 224 | * alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After 225 | * header. If no Retry-After is given, the client SHOULD handle the response as it would for a 500 226 | * response. 227 | */ 228 | class MVS_API ServiceUnavailableException : public ServException { 229 | public: 230 | explicit ServiceUnavailableException(string_view what) noexcept : ServException{what} {} 231 | ~ServiceUnavailableException() noexcept override; 232 | 233 | // Copy. 234 | ServiceUnavailableException(const ServiceUnavailableException&) noexcept = default; 235 | ServiceUnavailableException& operator=(const ServiceUnavailableException&) noexcept = default; 236 | 237 | // Move. 238 | ServiceUnavailableException(ServiceUnavailableException&&) noexcept = default; 239 | ServiceUnavailableException& operator=(ServiceUnavailableException&&) noexcept = default; 240 | 241 | int httpStatus() const noexcept override; 242 | 243 | const char* httpReason() const noexcept override; 244 | }; 245 | 246 | /** 247 | * The request requires user authentication. The response MUST include a WWW-Authenticate header 248 | * field (section 14.47) containing a challenge applicable to the requested resource. The client MAY 249 | * repeat the request with a suitable Authorization header field (section 14.8). If the request 250 | * already included Authorization credentials, then the 401 response indicates that authorization 251 | * has been refused for those credentials. If the 401 response contains the same challenge as the 252 | * prior response, and the user agent has already attempted authentication at least once, then the 253 | * user SHOULD be presented the entity that was given in the response, since that entity might 254 | * include relevant diagnostic information. HTTP access authentication is explained in "HTTP 255 | * Authentication: Basic and Digest Access Authentication". 256 | */ 257 | class MVS_API UnauthorizedException : public ServException { 258 | public: 259 | explicit UnauthorizedException(string_view what) noexcept : ServException{what} {} 260 | ~UnauthorizedException() noexcept override; 261 | 262 | // Copy. 263 | UnauthorizedException(const UnauthorizedException&) noexcept = default; 264 | UnauthorizedException& operator=(const UnauthorizedException&) noexcept = default; 265 | 266 | // Move. 267 | UnauthorizedException(UnauthorizedException&&) noexcept = default; 268 | UnauthorizedException& operator=(UnauthorizedException&&) noexcept = default; 269 | 270 | int httpStatus() const noexcept override; 271 | 272 | const char* httpReason() const noexcept override; 273 | }; 274 | 275 | } // mgbubble 276 | 277 | /** @} */ 278 | 279 | -------------------------------------------------------------------------------- /contrib/jsoncpp/json/json-forwards.h: -------------------------------------------------------------------------------- 1 | /// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). 2 | /// It is intended to be used with #include "json/json-forwards.h" 3 | /// This header provides forward declaration for all JsonCpp types. 4 | 5 | // ////////////////////////////////////////////////////////////////////// 6 | // Beginning of content of file: LICENSE 7 | // ////////////////////////////////////////////////////////////////////// 8 | 9 | /* 10 | The JsonCpp library's source code, including accompanying documentation, 11 | tests and demonstration applications, are licensed under the following 12 | conditions... 13 | 14 | Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all 15 | jurisdictions which recognize such a disclaimer. In such jurisdictions, 16 | this software is released into the Public Domain. 17 | 18 | In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 19 | 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and 20 | The JsonCpp Authors, and is released under the terms of the MIT License (see below). 21 | 22 | In jurisdictions which recognize Public Domain property, the user of this 23 | software may choose to accept it either as 1) Public Domain, 2) under the 24 | conditions of the MIT License (see below), or 3) under the terms of dual 25 | Public Domain/MIT License conditions described here, as they choose. 26 | 27 | The MIT License is about as close to Public Domain as a license can get, and is 28 | described in clear, concise terms at: 29 | 30 | http://en.wikipedia.org/wiki/MIT_License 31 | 32 | The full text of the MIT License follows: 33 | 34 | ======================================================================== 35 | Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 36 | 37 | Permission is hereby granted, free of charge, to any person 38 | obtaining a copy of this software and associated documentation 39 | files (the "Software"), to deal in the Software without 40 | restriction, including without limitation the rights to use, copy, 41 | modify, merge, publish, distribute, sublicense, and/or sell copies 42 | of the Software, and to permit persons to whom the Software is 43 | furnished to do so, subject to the following conditions: 44 | 45 | The above copyright notice and this permission notice shall be 46 | included in all copies or substantial portions of the Software. 47 | 48 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 49 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 50 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 51 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 52 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 53 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 54 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. 56 | ======================================================================== 57 | (END LICENSE TEXT) 58 | 59 | The MIT license is compatible with both the GPL and commercial 60 | software, affording one all of the rights of Public Domain with the 61 | minor nuisance of being required to keep the above copyright notice 62 | and license text in the source code. Note also that by accepting the 63 | Public Domain "license" you can re-license your copy using whatever 64 | license you like. 65 | 66 | */ 67 | 68 | // ////////////////////////////////////////////////////////////////////// 69 | // End of content of file: LICENSE 70 | // ////////////////////////////////////////////////////////////////////// 71 | 72 | 73 | 74 | 75 | 76 | #ifndef JSON_FORWARD_AMALGATED_H_INCLUDED 77 | # define JSON_FORWARD_AMALGATED_H_INCLUDED 78 | /// If defined, indicates that the source file is amalgated 79 | /// to prevent private header inclusion. 80 | #define JSON_IS_AMALGAMATION 81 | 82 | // ////////////////////////////////////////////////////////////////////// 83 | // Beginning of content of file: include/json/config.h 84 | // ////////////////////////////////////////////////////////////////////// 85 | 86 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 87 | // Distributed under MIT license, or public domain if desired and 88 | // recognized in your jurisdiction. 89 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 90 | 91 | #ifndef JSON_CONFIG_H_INCLUDED 92 | #define JSON_CONFIG_H_INCLUDED 93 | #include 94 | #include //typedef String 95 | #include //typedef int64_t, uint64_t 96 | 97 | /// If defined, indicates that json library is embedded in CppTL library. 98 | //# define JSON_IN_CPPTL 1 99 | 100 | /// If defined, indicates that json may leverage CppTL library 101 | //# define JSON_USE_CPPTL 1 102 | /// If defined, indicates that cpptl vector based map should be used instead of 103 | /// std::map 104 | /// as Value container. 105 | //# define JSON_USE_CPPTL_SMALLMAP 1 106 | 107 | // If non-zero, the library uses exceptions to report bad input instead of C 108 | // assertion macros. The default is to use exceptions. 109 | #ifndef JSON_USE_EXCEPTION 110 | #define JSON_USE_EXCEPTION 1 111 | #endif 112 | 113 | /// If defined, indicates that the source file is amalgated 114 | /// to prevent private header inclusion. 115 | /// Remarks: it is automatically defined in the generated amalgated header. 116 | // #define JSON_IS_AMALGAMATION 117 | 118 | #ifdef JSON_IN_CPPTL 119 | #include 120 | #ifndef JSON_USE_CPPTL 121 | #define JSON_USE_CPPTL 1 122 | #endif 123 | #endif 124 | 125 | #ifdef JSON_IN_CPPTL 126 | #define JSON_API CPPTL_API 127 | #elif defined(JSON_DLL_BUILD) 128 | #if defined(_MSC_VER) || defined(__MINGW32__) 129 | #define JSON_API __declspec(dllexport) 130 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 131 | #endif // if defined(_MSC_VER) 132 | #elif defined(JSON_DLL) 133 | #if defined(_MSC_VER) || defined(__MINGW32__) 134 | #define JSON_API __declspec(dllimport) 135 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 136 | #endif // if defined(_MSC_VER) 137 | #endif // ifdef JSON_IN_CPPTL 138 | #if !defined(JSON_API) 139 | #define JSON_API 140 | #endif 141 | 142 | // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for 143 | // integer 144 | // Storages, and 64 bits integer support is disabled. 145 | // #define JSON_NO_INT64 1 146 | 147 | #if defined(_MSC_VER) // MSVC 148 | # if _MSC_VER <= 1200 // MSVC 6 149 | // Microsoft Visual Studio 6 only support conversion from __int64 to double 150 | // (no conversion from unsigned __int64). 151 | # define JSON_USE_INT64_DOUBLE_CONVERSION 1 152 | // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' 153 | // characters in the debug information) 154 | // All projects I've ever seen with VS6 were using this globally (not bothering 155 | // with pragma push/pop). 156 | # pragma warning(disable : 4786) 157 | # endif // MSVC 6 158 | 159 | # if _MSC_VER >= 1500 // MSVC 2008 160 | /// Indicates that the following function is deprecated. 161 | # define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) 162 | # endif 163 | 164 | #endif // defined(_MSC_VER) 165 | 166 | // In c++11 the override keyword allows you to explicity define that a function 167 | // is intended to override the base-class version. This makes the code more 168 | // managable and fixes a set of common hard-to-find bugs. 169 | #if __cplusplus >= 201103L 170 | # define JSONCPP_OVERRIDE override 171 | # define JSONCPP_NOEXCEPT noexcept 172 | #elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900 173 | # define JSONCPP_OVERRIDE override 174 | # define JSONCPP_NOEXCEPT throw() 175 | #elif defined(_MSC_VER) && _MSC_VER >= 1900 176 | # define JSONCPP_OVERRIDE override 177 | # define JSONCPP_NOEXCEPT noexcept 178 | #else 179 | # define JSONCPP_OVERRIDE 180 | # define JSONCPP_NOEXCEPT throw() 181 | #endif 182 | 183 | #ifndef JSON_HAS_RVALUE_REFERENCES 184 | 185 | #if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010 186 | #define JSON_HAS_RVALUE_REFERENCES 1 187 | #endif // MSVC >= 2010 188 | 189 | #ifdef __clang__ 190 | #if __has_feature(cxx_rvalue_references) 191 | #define JSON_HAS_RVALUE_REFERENCES 1 192 | #endif // has_feature 193 | 194 | #elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) 195 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) 196 | #define JSON_HAS_RVALUE_REFERENCES 1 197 | #endif // GXX_EXPERIMENTAL 198 | 199 | #endif // __clang__ || __GNUC__ 200 | 201 | #endif // not defined JSON_HAS_RVALUE_REFERENCES 202 | 203 | #ifndef JSON_HAS_RVALUE_REFERENCES 204 | #define JSON_HAS_RVALUE_REFERENCES 0 205 | #endif 206 | 207 | #ifdef __clang__ 208 | # if __has_extension(attribute_deprecated_with_message) 209 | # define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) 210 | # endif 211 | #elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) 212 | # if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) 213 | # define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) 214 | # elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) 215 | # define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) 216 | # endif // GNUC version 217 | #endif // __clang__ || __GNUC__ 218 | 219 | #if !defined(JSONCPP_DEPRECATED) 220 | #define JSONCPP_DEPRECATED(message) 221 | #endif // if !defined(JSONCPP_DEPRECATED) 222 | 223 | #if __GNUC__ >= 6 224 | # define JSON_USE_INT64_DOUBLE_CONVERSION 1 225 | #endif 226 | 227 | #if !defined(JSON_IS_AMALGAMATION) 228 | 229 | # include "version.h" 230 | 231 | # if JSONCPP_USING_SECURE_MEMORY 232 | # include "allocator.h" //typedef Allocator 233 | # endif 234 | 235 | #endif // if !defined(JSON_IS_AMALGAMATION) 236 | 237 | namespace Json { 238 | typedef int Int; 239 | typedef unsigned int UInt; 240 | #if defined(JSON_NO_INT64) 241 | typedef int LargestInt; 242 | typedef unsigned int LargestUInt; 243 | #undef JSON_HAS_INT64 244 | #else // if defined(JSON_NO_INT64) 245 | // For Microsoft Visual use specific types as long long is not supported 246 | #if defined(_MSC_VER) // Microsoft Visual Studio 247 | typedef __int64 Int64; 248 | typedef unsigned __int64 UInt64; 249 | #else // if defined(_MSC_VER) // Other platforms, use long long 250 | typedef int64_t Int64; 251 | typedef uint64_t UInt64; 252 | #endif // if defined(_MSC_VER) 253 | typedef Int64 LargestInt; 254 | typedef UInt64 LargestUInt; 255 | #define JSON_HAS_INT64 256 | #endif // if defined(JSON_NO_INT64) 257 | #if JSONCPP_USING_SECURE_MEMORY 258 | #define JSONCPP_STRING std::basic_string, Json::SecureAllocator > 259 | #define JSONCPP_OSTRINGSTREAM std::basic_ostringstream, Json::SecureAllocator > 260 | #define JSONCPP_OSTREAM std::basic_ostream> 261 | #define JSONCPP_ISTRINGSTREAM std::basic_istringstream, Json::SecureAllocator > 262 | #define JSONCPP_ISTREAM std::istream 263 | #else 264 | #define JSONCPP_STRING std::string 265 | #define JSONCPP_OSTRINGSTREAM std::ostringstream 266 | #define JSONCPP_OSTREAM std::ostream 267 | #define JSONCPP_ISTRINGSTREAM std::istringstream 268 | #define JSONCPP_ISTREAM std::istream 269 | #endif // if JSONCPP_USING_SECURE_MEMORY 270 | } // end namespace Json 271 | 272 | #endif // JSON_CONFIG_H_INCLUDED 273 | 274 | // ////////////////////////////////////////////////////////////////////// 275 | // End of content of file: include/json/config.h 276 | // ////////////////////////////////////////////////////////////////////// 277 | 278 | 279 | 280 | 281 | 282 | 283 | // ////////////////////////////////////////////////////////////////////// 284 | // Beginning of content of file: include/json/forwards.h 285 | // ////////////////////////////////////////////////////////////////////// 286 | 287 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 288 | // Distributed under MIT license, or public domain if desired and 289 | // recognized in your jurisdiction. 290 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 291 | 292 | #ifndef JSON_FORWARDS_H_INCLUDED 293 | #define JSON_FORWARDS_H_INCLUDED 294 | 295 | #if !defined(JSON_IS_AMALGAMATION) 296 | #include "config.h" 297 | #endif // if !defined(JSON_IS_AMALGAMATION) 298 | 299 | namespace Json { 300 | 301 | // writer.h 302 | class FastWriter; 303 | class StyledWriter; 304 | 305 | // reader.h 306 | class Reader; 307 | 308 | // features.h 309 | class Features; 310 | 311 | // value.h 312 | typedef unsigned int ArrayIndex; 313 | class StaticString; 314 | class Path; 315 | class PathArgument; 316 | class Value; 317 | class ValueIteratorBase; 318 | class ValueIterator; 319 | class ValueConstIterator; 320 | 321 | } // namespace Json 322 | 323 | #endif // JSON_FORWARDS_H_INCLUDED 324 | 325 | // ////////////////////////////////////////////////////////////////////// 326 | // End of content of file: include/json/forwards.h 327 | // ////////////////////////////////////////////////////////////////////// 328 | 329 | 330 | 331 | 332 | 333 | #endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED 334 | -------------------------------------------------------------------------------- /include/sqlite3pp/sqlite3pp.ipp: -------------------------------------------------------------------------------- 1 | // sqlite3pp.cpp 2 | // 3 | // The MIT License 4 | // 5 | // Copyright (c) 2015 Wongoo Lee (iwongu at gmail dot com) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | #include 26 | #include 27 | 28 | namespace sqlite3pp 29 | { 30 | 31 | namespace 32 | { 33 | null_type ignore; 34 | 35 | int busy_handler_impl(void* p, int cnt) 36 | { 37 | auto h = static_cast(p); 38 | return (*h)(cnt); 39 | } 40 | 41 | int commit_hook_impl(void* p) 42 | { 43 | auto h = static_cast(p); 44 | return (*h)(); 45 | } 46 | 47 | void rollback_hook_impl(void* p) 48 | { 49 | auto h = static_cast(p); 50 | (*h)(); 51 | } 52 | 53 | void update_hook_impl(void* p, int opcode, char const* dbname, char const* tablename, long long int rowid) 54 | { 55 | auto h = static_cast(p); 56 | (*h)(opcode, dbname, tablename, rowid); 57 | } 58 | 59 | int authorizer_impl(void* p, int evcode, char const* p1, char const* p2, char const* dbname, char const* tvname) 60 | { 61 | auto h = static_cast(p); 62 | return (*h)(evcode, p1, p2, dbname, tvname); 63 | } 64 | 65 | } // namespace 66 | 67 | inline database::database(char const* dbname, int flags, char const* vfs) : db_(nullptr), borrowing_(false) 68 | { 69 | if (dbname) { 70 | auto rc = connect(dbname, flags, vfs); 71 | if (rc != SQLITE_OK) 72 | throw database_error("can't connect database"); 73 | } 74 | } 75 | 76 | inline database::database(database&& db) : db_(std::move(db.db_)), 77 | borrowing_(std::move(db.borrowing_)), 78 | bh_(std::move(db.bh_)), 79 | ch_(std::move(db.ch_)), 80 | rh_(std::move(db.rh_)), 81 | uh_(std::move(db.uh_)), 82 | ah_(std::move(db.ah_)) 83 | { 84 | db.db_ = nullptr; 85 | } 86 | 87 | inline database& database::operator=(database&& db) 88 | { 89 | db_ = std::move(db.db_); 90 | db.db_ = nullptr; 91 | borrowing_ = std::move(db.borrowing_); 92 | 93 | bh_ = std::move(db.bh_); 94 | ch_ = std::move(db.ch_); 95 | rh_ = std::move(db.rh_); 96 | uh_ = std::move(db.uh_); 97 | ah_ = std::move(db.ah_); 98 | 99 | return *this; 100 | } 101 | 102 | inline database::~database() 103 | { 104 | if (!borrowing_) { 105 | disconnect(); 106 | } 107 | } 108 | 109 | inline int database::connect(char const* dbname, int flags, char const* vfs) 110 | { 111 | if (!borrowing_) { 112 | disconnect(); 113 | } 114 | 115 | return sqlite3_open_v2(dbname, &db_, flags, vfs); 116 | } 117 | 118 | inline int database::disconnect() 119 | { 120 | auto rc = SQLITE_OK; 121 | if (db_) { 122 | rc = sqlite3_close(db_); 123 | if (rc == SQLITE_OK) { 124 | db_ = nullptr; 125 | } 126 | } 127 | 128 | return rc; 129 | } 130 | 131 | inline int database::attach(char const* dbname, char const* name) 132 | { 133 | return executef("ATTACH '%q' AS '%q'", dbname, name); 134 | } 135 | 136 | inline int database::detach(char const* name) 137 | { 138 | return executef("DETACH '%q'", name); 139 | } 140 | 141 | inline int database::backup(database& destdb, backup_handler h) 142 | { 143 | return backup("main", destdb, "main", h); 144 | } 145 | 146 | inline int database::backup(char const* dbname, database& destdb, char const* destdbname, backup_handler h, int step_page) 147 | { 148 | sqlite3_backup* bkup = sqlite3_backup_init(destdb.db_, destdbname, db_, dbname); 149 | if (!bkup) { 150 | return error_code(); 151 | } 152 | auto rc = SQLITE_OK; 153 | do { 154 | rc = sqlite3_backup_step(bkup, step_page); 155 | if (h) { 156 | h(sqlite3_backup_remaining(bkup), sqlite3_backup_pagecount(bkup), rc); 157 | } 158 | } while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED); 159 | sqlite3_backup_finish(bkup); 160 | return rc; 161 | } 162 | 163 | inline void database::set_busy_handler(busy_handler h) 164 | { 165 | bh_ = h; 166 | sqlite3_busy_handler(db_, bh_ ? busy_handler_impl : 0, &bh_); 167 | } 168 | 169 | inline void database::set_commit_handler(commit_handler h) 170 | { 171 | ch_ = h; 172 | sqlite3_commit_hook(db_, ch_ ? commit_hook_impl : 0, &ch_); 173 | } 174 | 175 | inline void database::set_rollback_handler(rollback_handler h) 176 | { 177 | rh_ = h; 178 | sqlite3_rollback_hook(db_, rh_ ? rollback_hook_impl : 0, &rh_); 179 | } 180 | 181 | inline void database::set_update_handler(update_handler h) 182 | { 183 | uh_ = h; 184 | sqlite3_update_hook(db_, uh_ ? update_hook_impl : 0, &uh_); 185 | } 186 | 187 | inline void database::set_authorize_handler(authorize_handler h) 188 | { 189 | ah_ = h; 190 | sqlite3_set_authorizer(db_, ah_ ? authorizer_impl : 0, &ah_); 191 | } 192 | 193 | inline long long int database::last_insert_rowid() const 194 | { 195 | return sqlite3_last_insert_rowid(db_); 196 | } 197 | 198 | inline int database::enable_foreign_keys(bool enable) 199 | { 200 | return sqlite3_db_config(db_, SQLITE_DBCONFIG_ENABLE_FKEY, enable ? 1 : 0, nullptr); 201 | } 202 | 203 | inline int database::enable_triggers(bool enable) 204 | { 205 | return sqlite3_db_config(db_, SQLITE_DBCONFIG_ENABLE_TRIGGER, enable ? 1 : 0, nullptr); 206 | } 207 | 208 | inline int database::enable_extended_result_codes(bool enable) 209 | { 210 | return sqlite3_extended_result_codes(db_, enable ? 1 : 0); 211 | } 212 | 213 | inline int database::changes() const 214 | { 215 | return sqlite3_changes(db_); 216 | } 217 | 218 | inline int database::error_code() const 219 | { 220 | return sqlite3_errcode(db_); 221 | } 222 | 223 | inline int database::extended_error_code() const 224 | { 225 | return sqlite3_extended_errcode(db_); 226 | } 227 | 228 | inline char const* database::error_msg() const 229 | { 230 | return sqlite3_errmsg(db_); 231 | } 232 | 233 | inline int database::execute(char const* sql) 234 | { 235 | return sqlite3_exec(db_, sql, 0, 0, 0); 236 | } 237 | 238 | inline int database::executef(char const* sql, ...) 239 | { 240 | va_list ap; 241 | va_start(ap, sql); 242 | std::shared_ptr msql(sqlite3_vmprintf(sql, ap), sqlite3_free); 243 | va_end(ap); 244 | 245 | return execute(msql.get()); 246 | } 247 | 248 | inline int database::set_busy_timeout(int ms) 249 | { 250 | return sqlite3_busy_timeout(db_, ms); 251 | } 252 | 253 | 254 | inline statement::statement(database& db, char const* stmt) : db_(db), stmt_(0), tail_(0) 255 | { 256 | if (stmt) { 257 | auto rc = prepare(stmt); 258 | if (rc != SQLITE_OK) 259 | throw database_error(db_); 260 | } 261 | } 262 | 263 | inline statement::~statement() 264 | { 265 | // finish() can return error. If you want to check the error, call 266 | // finish() explicitly before this object is destructed. 267 | finish(); 268 | } 269 | 270 | inline int statement::prepare(char const* stmt) 271 | { 272 | auto rc = finish(); 273 | if (rc != SQLITE_OK) 274 | return rc; 275 | 276 | return prepare_impl(stmt); 277 | } 278 | 279 | inline int statement::prepare_impl(char const* stmt) 280 | { 281 | return sqlite3_prepare_v2(db_.db_, stmt, std::strlen(stmt), &stmt_, &tail_); 282 | } 283 | 284 | inline int statement::finish() 285 | { 286 | auto rc = SQLITE_OK; 287 | if (stmt_) { 288 | rc = finish_impl(stmt_); 289 | stmt_ = nullptr; 290 | } 291 | tail_ = nullptr; 292 | 293 | return rc; 294 | } 295 | 296 | inline int statement::finish_impl(sqlite3_stmt* stmt) 297 | { 298 | return sqlite3_finalize(stmt); 299 | } 300 | 301 | inline int statement::step() 302 | { 303 | return sqlite3_step(stmt_); 304 | } 305 | 306 | inline int statement::reset() 307 | { 308 | return sqlite3_reset(stmt_); 309 | } 310 | 311 | inline int statement::bind(int idx, int value) 312 | { 313 | return sqlite3_bind_int(stmt_, idx, value); 314 | } 315 | 316 | inline int statement::bind(int idx, double value) 317 | { 318 | return sqlite3_bind_double(stmt_, idx, value); 319 | } 320 | 321 | inline int statement::bind(int idx, long long int value) 322 | { 323 | return sqlite3_bind_int64(stmt_, idx, value); 324 | } 325 | 326 | inline int statement::bind(int idx, char const* value, copy_semantic fcopy) 327 | { 328 | return sqlite3_bind_text(stmt_, idx, value, std::strlen(value), fcopy == copy ? SQLITE_TRANSIENT : SQLITE_STATIC ); 329 | } 330 | 331 | inline int statement::bind(int idx, void const* value, int n, copy_semantic fcopy) 332 | { 333 | return sqlite3_bind_blob(stmt_, idx, value, n, fcopy == copy ? SQLITE_TRANSIENT : SQLITE_STATIC ); 334 | } 335 | 336 | inline int statement::bind(int idx, std::string const& value, copy_semantic fcopy) 337 | { 338 | return sqlite3_bind_text(stmt_, idx, value.c_str(), value.size(), fcopy == copy ? SQLITE_TRANSIENT : SQLITE_STATIC ); 339 | } 340 | 341 | inline int statement::bind(int idx) 342 | { 343 | return sqlite3_bind_null(stmt_, idx); 344 | } 345 | 346 | inline int statement::bind(int idx, null_type) 347 | { 348 | return bind(idx); 349 | } 350 | 351 | inline int statement::bind(char const* name, int value) 352 | { 353 | auto idx = sqlite3_bind_parameter_index(stmt_, name); 354 | return bind(idx, value); 355 | } 356 | 357 | inline int statement::bind(char const* name, double value) 358 | { 359 | auto idx = sqlite3_bind_parameter_index(stmt_, name); 360 | return bind(idx, value); 361 | } 362 | 363 | inline int statement::bind(char const* name, long long int value) 364 | { 365 | auto idx = sqlite3_bind_parameter_index(stmt_, name); 366 | return bind(idx, value); 367 | } 368 | 369 | inline int statement::bind(char const* name, char const* value, copy_semantic fcopy) 370 | { 371 | auto idx = sqlite3_bind_parameter_index(stmt_, name); 372 | return bind(idx, value, fcopy); 373 | } 374 | 375 | inline int statement::bind(char const* name, void const* value, int n, copy_semantic fcopy) 376 | { 377 | auto idx = sqlite3_bind_parameter_index(stmt_, name); 378 | return bind(idx, value, n, fcopy); 379 | } 380 | 381 | inline int statement::bind(char const* name, std::string const& value, copy_semantic fcopy) 382 | { 383 | auto idx = sqlite3_bind_parameter_index(stmt_, name); 384 | return bind(idx, value, fcopy); 385 | } 386 | 387 | inline int statement::bind(char const* name) 388 | { 389 | auto idx = sqlite3_bind_parameter_index(stmt_, name); 390 | return bind(idx); 391 | } 392 | 393 | inline int statement::bind(char const* name, null_type) 394 | { 395 | return bind(name); 396 | } 397 | 398 | 399 | inline command::bindstream::bindstream(command& cmd, int idx) : cmd_(cmd), idx_(idx) 400 | { 401 | } 402 | 403 | inline command::command(database& db, char const* stmt) : statement(db, stmt) 404 | { 405 | } 406 | 407 | inline command::bindstream command::binder(int idx) 408 | { 409 | return bindstream(*this, idx); 410 | } 411 | 412 | inline int command::execute() 413 | { 414 | auto rc = step(); 415 | if (rc == SQLITE_DONE) rc = SQLITE_OK; 416 | 417 | return rc; 418 | } 419 | 420 | inline int command::execute_all() 421 | { 422 | auto rc = execute(); 423 | if (rc != SQLITE_OK) return rc; 424 | 425 | char const* sql = tail_; 426 | 427 | while (std::strlen(sql) > 0) { // sqlite3_complete() is broken. 428 | sqlite3_stmt* old_stmt = stmt_; 429 | 430 | if ((rc = prepare_impl(sql)) != SQLITE_OK) return rc; 431 | 432 | if ((rc = sqlite3_transfer_bindings(old_stmt, stmt_)) != SQLITE_OK) return rc; 433 | 434 | finish_impl(old_stmt); 435 | 436 | if ((rc = execute()) != SQLITE_OK) return rc; 437 | 438 | sql = tail_; 439 | } 440 | 441 | return rc; 442 | } 443 | 444 | 445 | inline query::rows::getstream::getstream(rows* rws, int idx) : rws_(rws), idx_(idx) 446 | { 447 | } 448 | 449 | inline query::rows::rows(sqlite3_stmt* stmt) : stmt_(stmt) 450 | { 451 | } 452 | 453 | inline int query::rows::data_count() const 454 | { 455 | return sqlite3_data_count(stmt_); 456 | } 457 | 458 | inline int query::rows::column_type(int idx) const 459 | { 460 | return sqlite3_column_type(stmt_, idx); 461 | } 462 | 463 | inline int query::rows::column_bytes(int idx) const 464 | { 465 | return sqlite3_column_bytes(stmt_, idx); 466 | } 467 | 468 | inline int query::rows::get(int idx, int) const 469 | { 470 | return sqlite3_column_int(stmt_, idx); 471 | } 472 | 473 | inline double query::rows::get(int idx, double) const 474 | { 475 | return sqlite3_column_double(stmt_, idx); 476 | } 477 | 478 | inline long long int query::rows::get(int idx, long long int) const 479 | { 480 | return sqlite3_column_int64(stmt_, idx); 481 | } 482 | 483 | inline char const* query::rows::get(int idx, char const*) const 484 | { 485 | return reinterpret_cast(sqlite3_column_text(stmt_, idx)); 486 | } 487 | 488 | inline std::string query::rows::get(int idx, std::string) const 489 | { 490 | return get(idx, (char const*)0); 491 | } 492 | 493 | inline void const* query::rows::get(int idx, void const*) const 494 | { 495 | return sqlite3_column_blob(stmt_, idx); 496 | } 497 | 498 | inline null_type query::rows::get(int /*idx*/, null_type) const 499 | { 500 | return ignore; 501 | } 502 | 503 | inline query::rows::getstream query::rows::getter(int idx) 504 | { 505 | return getstream(this, idx); 506 | } 507 | 508 | inline query::query_iterator::query_iterator() : cmd_(0) 509 | { 510 | rc_ = SQLITE_DONE; 511 | } 512 | 513 | inline query::query_iterator::query_iterator(query* cmd) : cmd_(cmd) 514 | { 515 | rc_ = cmd_->step(); 516 | if (rc_ != SQLITE_ROW && rc_ != SQLITE_DONE) 517 | throw database_error(cmd_->db_); 518 | } 519 | 520 | inline bool query::query_iterator::operator==(query::query_iterator const& other) const 521 | { 522 | return rc_ == other.rc_; 523 | } 524 | 525 | inline bool query::query_iterator::operator!=(query::query_iterator const& other) const 526 | { 527 | return rc_ != other.rc_; 528 | } 529 | 530 | inline query::query_iterator& query::query_iterator::operator++() 531 | { 532 | rc_ = cmd_->step(); 533 | if (rc_ != SQLITE_ROW && rc_ != SQLITE_DONE) 534 | throw database_error(cmd_->db_); 535 | return *this; 536 | } 537 | 538 | inline query::query_iterator::value_type query::query_iterator::operator*() const 539 | { 540 | return rows(cmd_->stmt_); 541 | } 542 | 543 | inline query::query(database& db, char const* stmt) : statement(db, stmt) 544 | { 545 | } 546 | 547 | inline int query::column_count() const 548 | { 549 | return sqlite3_column_count(stmt_); 550 | } 551 | 552 | inline char const* query::column_name(int idx) const 553 | { 554 | return sqlite3_column_name(stmt_, idx); 555 | } 556 | 557 | inline char const* query::column_decltype(int idx) const 558 | { 559 | return sqlite3_column_decltype(stmt_, idx); 560 | } 561 | 562 | 563 | inline query::iterator query::begin() 564 | { 565 | return query_iterator(this); 566 | } 567 | 568 | inline query::iterator query::end() 569 | { 570 | return query_iterator(); 571 | } 572 | 573 | 574 | inline transaction::transaction(database& db, bool fcommit, bool freserve) : db_(&db), fcommit_(fcommit) 575 | { 576 | int rc = db_->execute(freserve ? "BEGIN IMMEDIATE" : "BEGIN"); 577 | if (rc != SQLITE_OK) 578 | throw database_error(*db_); 579 | } 580 | 581 | inline transaction::~transaction() 582 | { 583 | if (db_) { 584 | // execute() can return error. If you want to check the error, 585 | // call commit() or rollback() explicitly before this object is 586 | // destructed. 587 | db_->execute(fcommit_ ? "COMMIT" : "ROLLBACK"); 588 | } 589 | } 590 | 591 | inline int transaction::commit() 592 | { 593 | auto db = db_; 594 | db_ = nullptr; 595 | int rc = db->execute("COMMIT"); 596 | return rc; 597 | } 598 | 599 | inline int transaction::rollback() 600 | { 601 | auto db = db_; 602 | db_ = nullptr; 603 | int rc = db->execute("ROLLBACK"); 604 | return rc; 605 | } 606 | 607 | 608 | inline database_error::database_error(char const* msg) : std::runtime_error(msg) 609 | { 610 | } 611 | 612 | inline database_error::database_error(database& db) : std::runtime_error(sqlite3_errmsg(db.db_)) 613 | { 614 | } 615 | 616 | } // namespace sqlite3pp 617 | --------------------------------------------------------------------------------