1.nodeos起来的时候main函数会执行各个plugin的startup方法
eos/programs/nodeos/main.cpp
int main(int argc, char** argv){
app().startup();
}
eos/libraries/appbase/application.cpp
void application::startup() {
for( auto plugin : initialized_plugins ) {
if( is_quiting() ) return;
plugin->startup(); //实际调用每个plugin的plugin_startup函数
}
}
2. chain_api_plugin的plugin_startup方法
eos/plugins/chain_api_plugin/chain_api_plugin.cpp
void chain_api_plugin::plugin_startup() {
//初始化ro_api (chain_plugin)
auto ro_api = app().get_plugin().get_read_only_api();
//初始化rw_api (chain_plugin)
auto rw_api = app().get_plugin().get_read_write_api();
//注册url与相应处理方法的
_http_plugin.add_api({
CHAIN_RW_CALL_ASYNC(push_transaction, chain_apis::read_write::push_transaction_results, 202),
});
}
3. add_api 函数
eos/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp
//注册url和对应的handler 方法
void add_api(const api_description& api) {
for (const auto& call : api)
add_handler(call.first, call.second);
}
4. add_handler函数
将url与处理方法的对应关系存入url_handlers(map)
eos/plugins/http_plugin/http_plugin.cpp
void http_plugin::add_handler(const string& url, const url_handler& handler) {
ilog( "add api url: ${c}", ("c",url) );
app().get_io_service().post([=](){
my->url_handlers.insert(std::make_pair(url,handler)); //注册url对应的处理方法
});
}
5. push_transaction的处理方法
CHAIN_RW_CALL_ASYNC
eos/plugins/chain_api_plugin/chain_api_plugin.cpp
rw_api:在chain_api_plugin的plugin_startup函数中被初始化
#define CHAIN_RW_CALL_ASYNC(call_name, call_result, http_response_code) CALL_ASYNC(chain, rw_api, chain_apis::read_write, call_name, call_result, http_response_code)
最终会调用api_handle(也就是rw_api) 的 call_name(传过来的方法名)。
例如:如果cleos发起的请求是 “v1/chain/push_transaction”,
那么call_name就是"push_transaction",这样最终调用push_transaction方法(实现在eos/plugins/chain_plugin/chain_plugin.cpp)
api_handle.call_name(fc::json::from_string(body).as(),\
6.收到cleos的网络请求后的处理步骤
上面我们讲到了plugin起来时,会将url与对应的处理方法注册在一个map (url_handlers)。
收到请求后,会从url获得resource,然后在url_handlers里查询对应的处理方法,触发它。
eos/plugins/http_plugin/http_plugin.cpp
template
void handle_http_request(typename websocketpp::server::connection_ptr con) {
auto resource = con->get_uri()->get_resource();
std::cout<<"test http_plugin.cpp handle_http_request resource: "<defer_http_response();
//触发该方法的执行
handler_itr->second( resource, body, [con]( auto code, auto&& body ) {
con->set_body( std::move( body ));
con->set_status( websocketpp::http::status_code::value( code ));
con->send_http_response();
} );
} else {
dlog( "404 - not found: ${ep}", ("ep", resource));
error_results results{websocketpp::http::status_code::not_found,
"Not Found", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, "Unknown Endpoint"
)), verbose_http_errors )};
con->set_body( fc::json::to_string( results ));
con->set_status( websocketpp::http::status_code::not_found );
}
}