Example #1
0
void protobuf_codec::handle_message(connection_ptr& conn) const
{
	loki::buffer* buffer = conn->get_buffer();
	while (buffer->data_size() >= MSG_NAME_LENGTH_SIZE + MIN_MSG_NAME_SIZE + MSG_HEADER_LENGTH)	
	{
		const uint32_t flag = buffer->get<uint32_t>();
		const uint32_t msg_len = flag & 0x0000ffff;
		if (msg_len + MSG_HEADER_LENGTH > buffer->data_size())
		{
			//message not enough, wait
			break;
		}
		if (msg_len > MAX_MSG_LENGTH || msg_len < MSG_NAME_LENGTH_SIZE + MIN_MSG_NAME_SIZE)
		{
			LOG(ERROR)<<"message length error "<<msg_len<<",readable="<<buffer->data_size();
			conn->close();
			break;
		}

		char buff[MAX_MSG_LENGTH];
		size_t len = sizeof(buff);
		LOG(INFO)<<__func__<<", flag="<<flag;
		bool ret = conn->restore_msg((const char*)buffer->data_ptr() + MSG_HEADER_LENGTH, flag, buff, len);
		if (!ret)
		{
			LOG(ERROR)<<"restore msg error";
			conn->close();
			break;
		}

		uint32_t errorcode = 0;
		MessagePtr message = parse(buff, len, errorcode);
		if (errorcode == 0 && message)
		{
			callback_(conn, message);
			buffer->consume(MSG_HEADER_LENGTH + msg_len);
		}
		else
		{
			LOG(ERROR)<<"Parse message error ,errorcode="<<errorcode;
			conn->close();
			break;
		}
	}
}
Example #2
0
 // close: - close this connection
 // close:all; close all connections
 void close_connection(connection_ptr connection) {
     if (connection){
         connection->close(close::status::NORMAL);
     } else {
         typename std::set<connection_ptr>::iterator it;
         
         for (it = m_connections.begin(); it != m_connections.end(); it++) {
             
             (*it)->close(close::status::NORMAL);
         }
     }
 }
Example #3
0
 /**
  * Sends a close signal to every connection with the specified code and 
  * reason. The default code is 1001/Going Away and the default reason is
  * blank. 
  * 
  * @param code The WebSocket close code to send to remote clients as the
  * reason that the connection is being closed.
  * @param reason The WebSocket close reason to send to remote clients as the
  * text reason that the connection is being closed. Must be valid UTF-8.
  */
 void close_all(close::status::value code = close::status::GOING_AWAY, 
                const std::string& reason = "")
 {
     boost::lock_guard<boost::recursive_mutex> lock(m_lock);
     
     m_alog->at(log::alevel::ENDPOINT) 
     << "Endpoint received signal to close all connections cleanly with code " 
     << code << " and reason " << reason << log::endl;
     
     // TODO: is there a more elegant way to do this? In some code paths 
     // close can call terminate immediately which removes the connection
     // from m_connections, invalidating the iterator.
     typename std::set<connection_ptr>::iterator it;
     
     for (it = m_connections.begin(); it != m_connections.end();) {
         const connection_ptr con = *it++;
         con->close(code,reason);
     }
 }
          /**
           *  Received in response to get_headers message, we should certify that we requested this.
           */
          void handle_headers( const connection_ptr& con,  chan_data& cdat, const headers_message& msg )
          { try {
              FC_ASSERT( !!cdat.requested_headers );
              cdat.requested_headers.reset();
              
              // TODO: validate that all ids reported have the min proof of work for a name.

              ilog( "received ${x} block headers", ("msg",msg.headers.size() ) );
              _fork_db.cache_header( msg.first );
              _new_block_info = true;
              name_id_type prev_id = msg.first.id();
              for( auto itr = msg.headers.begin(); itr != msg.headers.end(); ++itr )
              {
                 name_header next_head( *itr, prev_id );
                 ilog( "${id} = ${next_head}", ("id",next_head.id())("next_head",next_head) );
                 _fork_db.cache_header( next_head );
                 prev_id = next_head.id();

                 if( prev_id > max_name_hash() )
                 {
                    // then we should disconnect.... 
                    wlog( "node produced name header with insufficient minimum work" );
                    con->close();
                    return;
                 }

                 cdat.available_blocks.insert(prev_id);
              }

              if( prev_id != msg.head_block_id )
              {
                  cdat.requested_headers = fc::time_point::now();
                  get_headers_message  request;
                  request.locator_hashes.push_back( prev_id );
                  con->send( network::message( request, _chan_id ) );
              }
              
          } FC_RETHROW_EXCEPTIONS( warn, "", ("msg",msg) ) } 
Example #5
0
/* Ends a test by canceling the timeout timer, marking the end time, generating
 * statistics and closing the websocket connection.
 */
void case_handler::end(connection_ptr con) {
    std::vector<double> avgs;
    avgs.resize(m_quantile_count, 0);
    
    std::vector<double> quantiles;
    quantiles.resize(m_quantile_count, 0);
    
    double avg = 0;
    double stddev = 0;
    double total = 0;
    double seconds = 0;
    
    if (m_timeout > 0) {
        m_timer->cancel();
    }
    
    // TODO: handle weird sizes and error conditions better
    if (m_end.size() > m_quantile_count) {
        boost::chrono::steady_clock::time_point last = m_start;
        
        // convert RTTs to microsecs
        //
        
        std::vector<boost::chrono::steady_clock::time_point>::iterator it;
        for (it = m_end.begin(); it != m_end.end(); ++it) {
            boost::chrono::nanoseconds dur = *it - last;
            m_times.push_back(static_cast<double> (dur.count()) / 1000.);
            last = *it;
        }
        
        std::sort(m_times.begin(), m_times.end());
        
        size_t samples_per_quantile = m_times.size() / m_quantile_count;
        
        // quantiles
        for (size_t i = 0; i < m_quantile_count; ++i) {
            quantiles[i] = m_times[((i + 1) * samples_per_quantile) - 1];
        }
        
        // total average and quantile averages
        for (size_t i = 0; i < m_times.size(); ++i) {
            avg += m_times[i];
            avgs[i / samples_per_quantile] 
                += m_times[i] / static_cast<double>(samples_per_quantile);
        }
        
        avg /= static_cast<double> (m_times.size());
        
        // standard dev corrected for estimation from sample
        for (size_t i = 0; i < m_times.size(); ++i) {
            stddev += (m_times[i] - avg) * (m_times[i] - avg);
        }
        
        // Bessel's correction
        stddev /= static_cast<double> (m_times.size() - 1); 
        stddev = std::sqrt(stddev);
    } else {
        m_times.push_back(0);
    }
    
    boost::chrono::nanoseconds total_dur = m_end[m_end.size()-1] - m_start;
    total = static_cast<double> (total_dur.count()) / 1000.; // microsec
    seconds = total / 10000000.;
    
    std::stringstream s;
    std::string outcome;
    
    switch (m_pass) {
        case FAIL:
            outcome = "fail";
            break;
        case PASS:
            outcome = "pass";
            break;
        case TIME_OUT:
            outcome = "time_out";
            break;
        case RUNNING:
            throw case_exception("end() called from RUNNING state");
            break;
    }
    
    s << "{\"result\":\"" << outcome 
      << "\",\"min\":" << m_times[0] 
      << ",\"max\":" << m_times[m_times.size()-1] 
      << ",\"median\":" << m_times[(m_times.size()-1)/2] 
      << ",\"avg\":" << avg 
      << ",\"stddev\":" << stddev 
      << ",\"total\":" << total 
      << ",\"bytes\":" << m_bytes 
      << ",\"quantiles\":[";
      
    for (size_t i = 0; i < m_quantile_count; i++) {
        s << (i > 0 ? "," : "");
        s << "[";
        s << avgs[i] << "," << quantiles[i];
        s << "]";
    }                 
    s << "]";
    
    if (m_rtts) {
        s << ",\"rtts\":[";
        for (size_t i = 0; i < m_times.size(); i++) {
            s << (i > 0 ? "," : "") << m_times[i];
        }
        s << "]";
    };
    s << "}";
    
    m_data = s.str();
    
    con->close(websocketpp::close::status::NORMAL,"");
}