/* ===================================================== */ void handle_message( const connection_ptr& con, const message& m ) { try { chan_data& cdat = get_channel_data(con); ilog( "${msg_type}", ("msg_type", (bitname::message_type)m.msg_type ) ); switch( (bitname::message_type)m.msg_type ) { case name_inv_msg: handle_name_inv( con, cdat, m.as<name_inv_message>() ); break; case block_inv_msg: handle_block_inv( con, cdat, m.as<block_inv_message>() ); break; case get_name_inv_msg: handle_get_name_inv( con, cdat, m.as<get_name_inv_message>() ); break; case get_headers_msg: handle_get_headers( con, cdat, m.as<get_headers_message>() ); break; case get_block_msg: handle_get_block( con, cdat, m.as<get_block_message>() ); break; case get_block_index_msg: handle_get_block_index( con, cdat, m.as<get_block_index_message>() ); break; case get_name_header_msg: handle_get_name( con, cdat, m.as<get_name_header_message>() ); break; case name_header_msg: handle_name( con, cdat, m.as<name_header_message>() ); break; case block_index_msg: handle_block_index( con, cdat, m.as<block_index_message>() ); break; case block_msg: handle_block( con, cdat, m.as<block_message>() ); break; case headers_msg: handle_headers( con, cdat, m.as<headers_message>() ); break; default: FC_THROW_EXCEPTION( exception, "unknown bitname message type ${msg_type}", ("msg_type", m.msg_type ) ); } } catch ( fc::exception& e ) { wlog( "${e} ${from}", ("e",e.to_detail_string())("from",con->remote_endpoint()) ); } } // handle_message
/** * For any given message id, there are many potential hosts from which it could be fetched. We * want to distribute the load across all hosts equally and therefore, the best one to fetch from * is the host that we have fetched the least from and that has fetched the most from us. * */ void fetch_from_best_connection( const std::vector<connection_ptr>& cons, const mini_pow& id ) { // if request is made, move id from unknown_msgs to requested_msgs // TODO: update this algorithm to be something better. for( uint32_t i = 0; i < cons.size(); ++i ) { bitchat_chan_data& cd = get_channel_data(cons[i]); if( cd.known_inv.find( id ) != cd.known_inv.end() ) { requested_msgs[id] = fc::time_point::now(); unknown_msgs.erase(id); cons[i]->send( network::message( get_priv_message( id ), chan_id ) ); return; } } }
/* ===================================================== * When a new node connects it must locate the best block chain that extends the * current known chain. **/ void request_block_headers( const connection_ptr& con ) { try { ilog( "requesting block headers from ${ep}", ("ep",con->remote_endpoint() )); chan_data& cdat = get_channel_data(con); if( cdat.requested_headers ) return; get_headers_message request; const std::vector<name_id_type>& ids = _name_db.get_header_ids(); uint32_t delta = 1; for( int32_t i = ids.size() - 1; i >= 0; ) { request.locator_hashes.push_back(ids[i]); i -= delta; delta *= 2; } cdat.requested_headers = fc::time_point::now(); con->send( network::message(request,_chan_id) ); } FC_RETHROW_EXCEPTIONS( warn, "") }
virtual void handle_message( const connection_ptr& c, const bts::network::message& m ) { bitchat_chan_data& cdat = get_channel_data(c); switch( (bitchat::message_type)m.msg_type ) { case inv_msg: handle_inv( c, cdat, m.as<inv_message>() ); break; case get_inv_msg: handle_get_inv( c, cdat, m.as<get_inv_message>() ); break; case get_priv_msg: handle_get_priv( c, cdat, m.as<get_priv_message>() ); break; case encrypted_msg: handle_priv_msg( c, cdat, m.as<encrypted_message>() ); break; default: wlog( "unknown bitchat message type ${t}", ("t",m.msg_type) ); } }
/** * Send any new inventory items that we have received since the last * broadcast to all connections that do not know about the inv item. */ void broadcast_inv() { if( new_msgs.size() ) { auto cons = peers->get_connections( chan_id ); for( auto c = cons.begin(); c != cons.end(); ++c ) { inv_message msg; bitchat_chan_data& cd = get_channel_data( *c ); for( uint32_t i = 0; i < new_msgs.size(); ++i ) { if( cd.known_inv.insert( new_msgs[i] ).second ) { msg.items.push_back( new_msgs[i] ); } } (*c)->send( network::message(msg,chan_id) ); } new_msgs.clear(); } }
// very_complex_array = archiver.values(key, names[], start, end, ...) xmlrpc_value *get_values(xmlrpc_env *env, xmlrpc_value *args, void *user) { #ifdef LOGFILE LOG_MSG("archiver.get_values\n"); #endif xmlrpc_value *names; xmlrpc_int32 key, start_sec, start_nano, end_sec, end_nano, count, how; xmlrpc_int32 actual_count; // Extract arguments xmlrpc_parse_value(env, args, "(iAiiiiii)", &key, &names, &start_sec, &start_nano, &end_sec, &end_nano, &count, &how); if (env->fault_occurred) return 0; #ifdef LOGFILE LOG_MSG("how=%d, count=%d\n", (int) how, (int) count); #endif if (count <= 1) count = 1; actual_count = count; if (count > 10000) // Upper limit to avoid outrageous requests. actual_count = 10000; // Build start/end epicsTime start, end; pieces2epicsTime(start_sec, start_nano, start); pieces2epicsTime(end_sec, end_nano, end); // Pull names into vector for SpreadsheetReader and just because. xmlrpc_value *name_val; char *name; int i; xmlrpc_int32 name_count = xmlrpc_array_size(env, names); stdVector<stdString> name_vector; name_vector.reserve(name_count); for (i=0; i<name_count; ++i) { // no new ref! name_val = xmlrpc_array_get_item(env, names, i); if (env->fault_occurred) return 0; xmlrpc_parse_value(env, name_val, "s", &name); if (env->fault_occurred) return 0; name_vector.push_back(stdString(name)); } // Build results switch (how) { case HOW_RAW: return get_channel_data(env, key, name_vector, start, end, actual_count, ReaderFactory::Raw, 0.0); case HOW_SHEET: return get_sheet_data(env, key, name_vector, start, end, actual_count, ReaderFactory::Raw, 0.0); case HOW_AVERAGE: return get_sheet_data(env, key, name_vector, start, end, actual_count, ReaderFactory::Average, (end-start)/count); case HOW_PLOTBIN: // 'count' = # of bins, resulting in up to 4*count samples return get_channel_data(env, key, name_vector, start, end, actual_count*4, ReaderFactory::Plotbin, (end-start)/count); case HOW_LINEAR: return get_sheet_data(env, key, name_vector, start, end, actual_count, ReaderFactory::Linear, (end-start)/count); } xmlrpc_env_set_fault_formatted(env, ARCH_DAT_ARG_ERROR, "Invalid how=%d", how); return 0; }
virtual void handle_subscribe( const connection_ptr& c ) { get_channel_data(c); // creates it... request_latest_blocks(); }