std::shared_ptr<const Msg> unmarshall(const_buffer<char> inb) { std::map<int, std::shared_ptr<BaseMarshall> >::iterator it; int type=ntohl(*reinterpret_cast<const int*> (inb.addr())); unsigned int len=ntohl(*reinterpret_cast<const unsigned int*> (inb.addr()+sizeof(int))); it=m_map.find(type); if(it==m_map.end()) throw std::runtime_error("marshalling:: message type not supported"); return it->second->unmarshall(const_buffer<char>(inb.addr()+HEAD_SIZE,len)); }
void UHPacket::parse_uh(const const_buffer<uint8_t> & uh_buf) { const uint8_t * buf = uh_buf.addr(); m_key.proto = *(buf + 0x0A); m_key.src_port = ntohs(*((uint16_t*)(buf + 0x1C))); m_key.dst_port = ntohs(*((uint16_t*)(buf + 0x1E))); m_key.src_ip4 = ntohl(*((uint32_t*)(buf + 0x2C))); m_key.dst_ip4 = ntohl(*((uint32_t*)(buf + 0x3C))); //m_tstamp = ntohl(*((uint32_t*)(buf + 0x10))); // FIXME: retype m_length = ntohs(*((uint16_t*)(buf + 0x0B))); m_caplen = 0; switch(*(buf + 0x08)) { case 0x40: m_pkttype = Packet::kPktTypeIP4; break; case 0x60: m_pkttype = Packet::kPktTypeIP6; break; default: m_pkttype = 0; break; } m_iptos = *(buf + 0x1A); m_ipttl = *(buf + 0x1B); m_machdr_parsed = true; m_iphdr_parsed = true; m_ports_parsed = true; m_l4hdr_parsed = true; }
int stream_socket::writev(const_buffer const &b) { static const unsigned max_vec_size = 16; const_buffer::buffer_data_type data = b.get(); unsigned size=0; #ifndef BOOSTER_WIN32 struct iovec vec[max_vec_size]; for(;size < max_vec_size && size < data.second;size++) { vec[size].iov_base = const_cast<char *>(data.first[size].ptr); vec[size].iov_len = data.first[size].size; } for(;;) { int ret = ::writev(native(),vec,size); if(ret >= 0) return ret; if(ret < 0 && errno==EINTR) continue; return ret; } #else // Win32 WSABUF vec[max_vec_size]; for(;size < max_vec_size && size < data.second;size++) { vec[size].buf = const_cast<char *>(data.first[size].ptr); vec[size].len = data.first[size].size; } DWORD send=0; int res = ::WSASend(native(),vec,size,&send,0,0,0); if(res == 0) return send; return -1; #endif }
void proxy::do_send(const std::string& command, const_buffer buffer, result_handler handler) { if (stopped()) { handler(error::channel_stopped); return; } LOG_DEBUG(LOG_NETWORK) << "Sending " << command << " to [" << authority() << "] (" << buffer.size() << " bytes)"; // Critical Section (protect socket) /////////////////////////////////////////////////////////////////////////// // The socket is locked until async_write returns. const auto socket = socket_->get_socket(); // The shared buffer is kept in scope until the handler is invoked. using namespace boost::asio; async_write(socket->get(), buffer, std::bind(&proxy::handle_send, shared_from_this(), _1, buffer, handler)); /////////////////////////////////////////////////////////////////////////// }
void proxy::handle_send(const boost_code& ec, const_buffer buffer, result_handler handler) { const auto error = code(error::boost_to_error_code(ec)); if (error) LOG_DEBUG(LOG_NETWORK) << "Failure sending " << buffer.size() << " byte message to [" << authority() << "] " << error.message(); handler(error); }
void proxy::handle_send(const boost_code& ec, const_buffer buffer, /*scope_lock::ptr lock,*/ result_handler handler) { ////lock = nullptr; //////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ const auto error = code(error::boost_to_error_code(ec)); if (error) log::debug(LOG_NETWORK) << "Failure sending " << buffer.size() << " byte message to [" << authority() << "] " << error.message(); handler(error); }
////// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ////// THIS REQUIRES AT LEAST TWO NETWORK THREADS TO PREVENT THREAD STARVATION. ////// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ////// The send subscriber pushes queued writes to the writer instead of having ////// writer pull them from a passive queue. This is less thread-efficient but it ////// allows us to reuse the subscriber and facilitates bypass of subscriber ////// queuing for large message types such as blocks, as we do with reads. bool proxy::do_send(const code&, const std::string& command, const_buffer buffer, result_handler handler) { if (stopped()) { handler(error::channel_stopped); return false; } ////if (ec) ////{ //// log::debug(LOG_NETWORK) //// << "Send dequeue failure [" << authority() << "] " << ec.message(); //// handler(ec); //// stop(ec); //// return false; ////} log::debug(LOG_NETWORK) << "Sending " << command << " to [" << authority() << "] (" << buffer.size() << " bytes)"; ////// Critical Section (protect writer) //////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ////// The lock must be held until the handler is invoked. ////const auto lock = std::make_shared<scope_lock>(mutex_); // Critical Section (protect socket) /////////////////////////////////////////////////////////////////////////// // The socket is locked until async_write returns. const auto socket = socket_->get_socket(); // The shared buffer must be kept in scope until the handler is invoked. using namespace boost::asio; async_write(socket->get(), buffer, std::bind(&proxy::handle_send, shared_from_this(), _1, buffer, /*lock,*/ handler)); return true; /////////////////////////////////////////////////////////////////////////// }