size_t udp_socket::send_to( const char* b, size_t l, const ip::endpoint& to ) { try { return my->_sock.send_to( boost::asio::buffer(b, l), to_asio_ep(to) ); } catch( const boost::system::system_error& e ) { if( e.code() == boost::asio::error::would_block ) { promise<size_t>::ptr p(new promise<size_t>("udp_socket::send_to")); my->_sock.async_send_to( boost::asio::buffer(b,l), to_asio_ep(to), [=]( const boost::system::error_code& ec, size_t bt ) { if( !ec ) p->set_value(bt); else p->set_exception( fc::exception_ptr( new fc::exception( FC_LOG_MESSAGE( error, "${message} ", ("message", boost::system::system_error(ec).what())) ) ) ); }); return p->wait(); } throw; } }
size_t udp_socket::receive_from( char* b, size_t l, fc::ip::endpoint& _from ) { try { boost::asio::ip::udp::endpoint from; size_t r = my->_sock.receive_from( boost::asio::buffer(b, l), from ); _from = to_fc_ep(from); return r; } catch( const boost::system::system_error& e ) { if( e.code() == boost::asio::error::would_block ) { boost::asio::ip::udp::endpoint from; promise<size_t>::ptr p(new promise<size_t>("udp_socket::send_to")); my->_sock.async_receive_from( boost::asio::buffer(b,l), from, [=]( const boost::system::error_code& ec, size_t bt ) { if( !ec ) p->set_value(bt); else p->set_exception( fc::exception_ptr( new fc::exception( FC_LOG_MESSAGE( error, "${message} ", ("message", boost::system::system_error(ec).what())) ) ) ); }); auto r = p->wait(); _from = to_fc_ep(from); return r; } throw; } }
void message_oriented_connection_impl::read_loop() { VERIFY_CORRECT_THREAD(); const unsigned int BUFFER_SIZE = 16; static_assert(BUFFER_SIZE >= sizeof(message_header), "insufficient buffer"); const int LEFTOVER = BUFFER_SIZE - sizeof(message_header); _connected_time = fc::time_point::now(); fc::oexception exception_to_rethrow; bool call_on_connection_closed = false; try { message m; while( true ) { char buffer[BUFFER_SIZE]; _sock.read(buffer, BUFFER_SIZE); _bytes_received += BUFFER_SIZE; memcpy((char*)&m, buffer, sizeof(message_header)); FC_ASSERT( m.size <= MAX_MESSAGE_SIZE, "", ("m.size",m.size)("MAX_MESSAGE_SIZE",MAX_MESSAGE_SIZE) ); size_t remaining_bytes_with_padding = 16 * ((m.size - LEFTOVER + 15) / 16); m.data.resize(LEFTOVER + remaining_bytes_with_padding); //give extra 16 bytes to allow for padding added in send call std::copy(buffer + sizeof(message_header), buffer + sizeof(buffer), m.data.begin()); if (remaining_bytes_with_padding) { _sock.read(&m.data[LEFTOVER], remaining_bytes_with_padding); _bytes_received += remaining_bytes_with_padding; } m.data.resize(m.size); // truncate off the padding bytes _last_message_received_time = fc::time_point::now(); try { // message handling errors are warnings... _delegate->on_message(_self, m); } /// Dedicated catches needed to distinguish from general fc::exception catch ( const fc::canceled_exception& e ) { throw e; } catch ( const fc::eof_exception& e ) { throw e; } catch ( const fc::exception& e) { /// Here loop should be continued so exception should be just caught locally. wlog( "message transmission failed ${er}", ("er", e.to_detail_string() ) ); throw; } } } catch ( const fc::canceled_exception& e ) { wlog( "caught a canceled_exception in read_loop. this should mean we're in the process of deleting this object already, so there's no need to notify the delegate: ${e}", ("e", e.to_detail_string() ) ); throw; } catch ( const fc::eof_exception& e ) { wlog( "disconnected ${e}", ("e", e.to_detail_string() ) ); call_on_connection_closed = true; } catch ( const fc::exception& e ) { elog( "disconnected ${er}", ("er", e.to_detail_string() ) ); call_on_connection_closed = true; exception_to_rethrow = fc::unhandled_exception(FC_LOG_MESSAGE(warn, "disconnected: ${e}", ("e", e.to_detail_string()))); } catch ( const std::exception& e ) { elog( "disconnected ${er}", ("er", e.what() ) ); call_on_connection_closed = true; exception_to_rethrow = fc::unhandled_exception(FC_LOG_MESSAGE(warn, "disconnected: ${e}", ("e", e.what()))); } catch ( ... ) { elog( "unexpected exception" ); call_on_connection_closed = true; exception_to_rethrow = fc::unhandled_exception(FC_LOG_MESSAGE(warn, "disconnected: ${e}", ("e", fc::except_str()))); } if (call_on_connection_closed) _delegate->on_connection_closed(_self); if (exception_to_rethrow) throw *exception_to_rethrow; }
iprocess& process::exec( const fc::path& exe, std::vector<std::string> args, const fc::path& work_dir, int opt ) { my->pctx.work_dir = work_dir.string(); my->pctx.suppress_console = (opt & suppress_console) != 0; if( opt&open_stdout) my->pctx.streams[boost::process::stdout_id] = bp::behavior::async_pipe(); else my->pctx.streams[boost::process::stdout_id] = bp::behavior::null(); if( opt& open_stderr ) my->pctx.streams[boost::process::stderr_id] = bp::behavior::async_pipe(); else my->pctx.streams[boost::process::stderr_id] = bp::behavior::null(); if( opt& open_stdin ) my->pctx.streams[boost::process::stdin_id] = bp::behavior::async_pipe(); else my->pctx.streams[boost::process::stdin_id] = bp::behavior::close(); /* std::vector<std::string> a; a.reserve(size_t(args.size())); for( uint32_t i = 0; i < args.size(); ++i ) { a.push_back( fc::move(args[i]) ); } */ my->child.reset( new bp::child( bp::create_child( exe.string(), fc::move(args), my->pctx ) ) ); if( opt & open_stdout ) { bp::handle outh = my->child->get_handle( bp::stdout_id ); my->_outp.reset( new bp::pipe( fc::asio::default_io_service(), outh.release() ) ); } if( opt & open_stderr ) { bp::handle errh = my->child->get_handle( bp::stderr_id ); my->_errp.reset( new bp::pipe( fc::asio::default_io_service(), errh.release() ) ); } if( opt & open_stdin ) { bp::handle inh = my->child->get_handle( bp::stdin_id ); my->_inp.reset( new bp::pipe( fc::asio::default_io_service(), inh.release() ) ); } promise<int>::ptr p(new promise<int>("process")); my->stat.async_wait( my->child->get_id(), [=]( const boost::system::error_code& ec, int exit_code ) { //slog( "process::result %d", exit_code ); if( !ec ) { #ifdef BOOST_POSIX_API if( WIFEXITED(exit_code) ) p->set_value( WEXITSTATUS(exit_code) ); else { p->set_exception( fc::exception_ptr( new fc::exception( FC_LOG_MESSAGE( error, "process exited with: ${message} ", ("message", strsignal(WTERMSIG(exit_code))) ) ) ) ); } #else p->set_value(exit_code); #endif } else { p->set_exception( fc::exception_ptr( new fc::exception( FC_LOG_MESSAGE( error, "process exited with: ${message} ", ("message", boost::system::system_error(ec).what())) ) ) ); } }); if( opt & open_stdin ) my->_in = std::make_shared<buffered_ostream>(std::make_shared<fc::asio::ostream<bp::pipe>>(my->_inp)); if( opt & open_stdout ) my->_out = std::make_shared<buffered_istream>(std::make_shared<fc::asio::istream<bp::pipe>>(my->_outp)); if( opt & open_stderr ) my->_err = std::make_shared<buffered_istream>(std::make_shared<fc::asio::istream<bp::pipe>>(my->_errp)); my->_exited = p; return *this; }