void net_io::do_write() { auto msg = _sq.peek(); if (nullptr == msg.get()) return; std::vector<blob> buffers; _parser->prepare_buffers_for_send(msg, buffers); std::vector<boost::asio::const_buffer> buffers2; for (auto& b : buffers) { buffers2.push_back(boost::asio::const_buffer(b.data(), b.length())); } add_reference(); boost::asio::async_write(_socket, buffers2, [this, msg](boost::system::error_code ec, std::size_t length) { if (!!ec) { on_failure(); } else { auto smsg = _sq.dequeue_peeked(); dassert(smsg == msg, "sent msg must be the first msg in send queue"); //dinfo("network message sent, rpc_id = %016llx", msg->header().rpc_id); do_write(); } release_reference(); }); }
void net_io::do_read(size_t sz) { add_reference(); void* ptr = _parser->read_buffer_ptr((int)sz); int remaining = _parser->read_buffer_capacity(); _socket.async_read_some(boost::asio::buffer(ptr, remaining), [this](boost::system::error_code ec, std::size_t length) { if (!!ec) { on_failure(); } else { int read_next; message_ptr msg = _parser->get_message_on_receive((int)length, read_next); while (msg != nullptr) { this->on_message_read(msg); msg = _parser->get_message_on_receive(0, read_next); } do_read(read_next); } release_reference(); }); }
/* ===== tls_access_next ========================================================== PRIVATE. Get access to the next entry/exit structure. Loose access to the current entry/exit structure. ================================================================================ */ _tls_entry_exit_t* tls_access_next (_tls_entry_exit_t* pCurrent) { _tls_entry_exit_t* p ; if (!pCurrent) return NULL ; tls_entry_exit_mutex_p () ; { // Get new reference on next. p = new_reference (pCurrent->next) ; // Release reference on current. release_reference (pCurrent) ; } tls_entry_exit_mutex_v () ; return p ; }
/* ===== tls_remove_entry_exit ==================================================== PRIVATE. Find an existing entry/exit structure, and remove it. The proc AND the param must match. ================================================================================ */ status_t tls_remove_entry_exit (bool bEntry, tls_proc_t proc, int param) { _tls_entry_exit_t* p = NULL ; _tls_entry_exit_t** ppNext = &gm_entry_proc_list ; // Check parameters. if (proc == NULL) return B_BAD_VALUE ; // Remove structure from the right list. // Note: list are processed IN the mutex zone, so we dont care of // managing useCount values. tls_entry_exit_mutex_p () ; { if (bEntry) // bEntry == PROC_ENTRY ppNext = &gm_entry_proc_list ; else // bEntry == PROC_EXIT ppNext = &gm_exit_proc_list ; // Find the structure. // Use the welle known algorithm which use list pointer links // address in place of value, to reach the last link address and // be able to update it. while (*ppNext != NULL) { // Check proc AND param. if ((*ppNext)->proc == proc && (*ppNext)->param == param) { // Founded. Remove it from the list. p = *ppNext ; *ppNext = (*ppNext)->next ; p->next = NULL ; // And delete it (if possible). release_reference (p) ; break ; } ppNext = &((*ppNext)->next) ; } } tls_entry_exit_mutex_v () ; // Finish. if (p != NULL) return B_NO_ERROR ; else return B_ERROR ; }
void client_net_io::connect() { session_state closed_state = SS_CLOSED; if (_state.compare_exchange_strong(closed_state, SS_CONNECTING)) { boost::asio::ip::tcp::endpoint ep( boost::asio::ip::address_v4(ntohl(_remote_addr.ip)), _remote_addr.port); add_reference(); _socket.async_connect(ep, [this](boost::system::error_code ec) { if (!ec) { _reconnect_count = 0; _state = SS_CONNECTED; dinfo("client session %s:%d connected", _remote_addr.name.c_str(), static_cast<int>(_remote_addr.port) ); set_options(); do_write(); do_read(); } else { derror("network client session connect failed, error = %s", ec.message().c_str() ); on_failure(); } release_reference(); }); } }