Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Resolve #12: Implement basic chain API
Browse files Browse the repository at this point in the history
Only one call, but that call works!
  • Loading branch information
nathanielhourt committed Apr 19, 2017
1 parent 9f70932 commit fcb8198
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 15 deletions.
1 change: 1 addition & 0 deletions plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ add_subdirectory(net_plugin)
add_subdirectory(p2p_plugin)
add_subdirectory(http_plugin)
add_subdirectory(chain_plugin)
add_subdirectory(chain_api_plugin)
add_subdirectory(producer_plugin)
16 changes: 16 additions & 0 deletions plugins/chain_api_plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
file(GLOB HEADERS "include/eos/chain_plugin/*.hpp")
add_library( chain_api_plugin
chain_api_plugin.cpp
${HEADERS} )

target_link_libraries( chain_api_plugin chain_plugin http_plugin appbase )
target_include_directories( chain_api_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )

install( TARGETS
chain_api_plugin

RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
install( FILES ${HEADERS} DESTINATION "include/eos/chain_api_plugin" )
48 changes: 48 additions & 0 deletions plugins/chain_api_plugin/chain_api_plugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <eos/chain_api_plugin/chain_api_plugin.hpp>
#include <eos/chain/exceptions.hpp>

#include <fc/io/json.hpp>

namespace eos {

using namespace eos;

class chain_api_plugin_impl {
public:
chain_api_plugin_impl(database& db)
: db(db) {}

void get_info(url_response_callback& cb) {
fc::mutable_variant_object response;

response["head_block_num"] = db.head_block_num();
response["head_block_id"] = db.head_block_id();
response["head_block_time"] = db.head_block_time();
response["head_block_producer"] = db.head_block_producer();
response["recent_slots"] = std::bitset<64>(db.get_dynamic_global_properties().recent_slots_filled).to_string();
response["participation_rate"] =
__builtin_popcountll(db.get_dynamic_global_properties().recent_slots_filled) / 64.0;

cb(200, fc::json::to_string(response));
}

database& db;
};


chain_api_plugin::chain_api_plugin()
:my(new chain_api_plugin_impl(app().get_plugin<chain_plugin>().db())) {}
chain_api_plugin::~chain_api_plugin(){}

void chain_api_plugin::set_program_options(options_description&, options_description&) {}
void chain_api_plugin::plugin_initialize(const variables_map&) {}

void chain_api_plugin::plugin_startup() {
app().get_plugin<http_plugin>().add_api({
{std::string("/v1/chain/get_info"), [this](string, string, url_response_callback cb) {my->get_info(cb);}}
});
}

void chain_api_plugin::plugin_shutdown() {}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once
#include <eos/chain_plugin/chain_plugin.hpp>
#include <eos/http_plugin/http_plugin.hpp>

#include <appbase/application.hpp>
#include <eos/chain/database.hpp>

namespace eos {
using eos::chain::database;
using std::unique_ptr;
using namespace appbase;

class chain_api_plugin : public plugin<chain_api_plugin> {
public:
APPBASE_PLUGIN_REQUIRES((chain_plugin)(http_plugin))

chain_api_plugin();
virtual ~chain_api_plugin();

virtual void set_program_options(options_description&, options_description&) override;

void plugin_initialize(const variables_map&);
void plugin_startup();
void plugin_shutdown();

private:
unique_ptr<class chain_api_plugin_impl> my;
};

}
9 changes: 3 additions & 6 deletions plugins/http_plugin/http_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,8 @@ namespace eos {
auto handler_itr = my->url_handlers.find(resource);
if(handler_itr != my->url_handlers.end()) {
handler_itr->second(resource, body, [con,this](int code, string body) {
my->http_ios.post([=]() {
con->set_body(body);
con->set_status(websocketpp::http::status_code::value(code));
});

This comment has been minimized.

Copy link
@nathanielhourt

nathanielhourt Apr 19, 2017

Author Contributor

@bytemaster Please review this. I made this change because before, the response body would always come back empty. The 404 response, circa line 133, was working so I removed the http_ios.post call to match, and now the normal response works. Is this correct?

con->set_body(body);
con->set_status(websocketpp::http::status_code::value(code));
});
} else {
wlog("404 - not found: ${ep}", ("ep",resource));
Expand Down Expand Up @@ -159,8 +157,7 @@ namespace eos {
}
}

void http_plugin::add_handler(const string& url, const url_handler& handler)
{
void http_plugin::add_handler(const string& url, const url_handler& handler) {
my->http_ios.post([=](){
my->url_handlers.insert(std::make_pair(url,handler));
});
Expand Down
34 changes: 28 additions & 6 deletions plugins/http_plugin/include/eos/http_plugin/http_plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,40 @@
namespace eos {
using namespace appbase;

/** this method type should be called by the url handler and should
* be passed the HTTP code and BODY to respond with.
/**
* @brief A callback function provided to a URL handler to
* allow it to specify the HTTP response code and body
*
* Arguments: response_code, response_body
*/
using url_response_callback = std::function<void(int,string)>;

/** url_handler receives the url, body, and callback handler
/**
* @brief Callback type for a URL handler
*
* URL handlers have this type
*
* The handler must gaurantee that url_response_callback() is called;
* otherwise, the connection will hang and result in a memory leak.
*
* The handler must gaurantee that url_response_callback() is called or
* the connection will hang and result in a memory leak.
* Arguments: url, request_body, response_callback
**/
using url_handler = std::function<void(string,string,url_response_callback)>;

/**
* @brief An API, containing URLs and handlers
*
* An API is composed of several calls, where each call has a URL and
* a handler. The URL is the path on the web server that triggers the
* call, and the handler is the function which implements the API call
*/
using api_description = std::map<string, url_handler>;

/**
* This plugin starts an HTTP server and dispatches queries to
* registered handles based upon URL. The handler is passed the
* URL that was requested and a callback method that should be
* called with the responce code and body.
* called with the response code and body.
*
* The handler will be called from the appbase application io_service
* thread. The callback can be called from any thread and will
Expand All @@ -44,6 +61,11 @@ namespace eos {
void plugin_shutdown();

void add_handler(const string& url, const url_handler&);
void add_api(const api_description& api) {
for (const auto& call : api)
add_handler(call.first, call.second);
}

private:
std::unique_ptr<class http_plugin_impl> my;
};
Expand Down
2 changes: 1 addition & 1 deletion programs/eosd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if( GPERFTOOLS_FOUND )
endif()

target_link_libraries( eosd
PRIVATE appbase producer_plugin chain_plugin net_plugin p2p_plugin http_plugin eos_chain fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
PRIVATE appbase chain_api_plugin producer_plugin chain_plugin net_plugin p2p_plugin http_plugin eos_chain fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )

install( TARGETS
eosd
Expand Down
4 changes: 2 additions & 2 deletions programs/eosd/main.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include <appbase/application.hpp>

#include <eos/p2p_plugin/p2p_plugin.hpp>
#include <eos/http_plugin/http_plugin.hpp>
#include <eos/producer_plugin/producer_plugin.hpp>
#include <eos/chain_api_plugin/chain_api_plugin.hpp>

#include <fc/log/logger_config.hpp>
#include <fc/exception/exception.hpp>
Expand All @@ -16,7 +16,7 @@ int main(int argc, char** argv)
{
try {
app().register_plugin<p2p_plugin>();
app().register_plugin<http_plugin>();
app().register_plugin<chain_api_plugin>();
app().register_plugin<producer_plugin>();

if(!app().initialize(argc, argv))
Expand Down

0 comments on commit fcb8198

Please sign in to comment.