void connection::handle_read(const asio::error_code& e, std::size_t bytes_transferred) { if (!e) { if (bytes_transferred != size) { Log("Did not receive proper amount of bytes : %d", size); connection_manager_.stop(shared_from_this()); return; } //printf("uid("XI64")\n", uid); // read object size if ((size > 8192*4) || (size <= 0)) { //ERROR - object too large - close connection connection_manager_.stop(shared_from_this()); return; } // parse packet request_.size = size; amf3parser * cparser = new amf3parser(buffer_.data()); request_.object = cparser->ReadNextObject(); request_.connection = this; try { request_handler_.handle_request(request_, reply_); } catch (std::exception& e) { std::cerr << "handle_request() exception: " << e.what() << "\n"; } delete cparser; if (reply_.objects.size() > 0) { // send reply packets try { socket_.write_some(reply_.to_buffers()); } catch (std::exception& e) { std::cerr << "asio::write_some() exception: " << e.what() << "\n"; } reply_.objects.clear(); // asio::async_write(socket_, reply_.to_buffers(), // boost::bind(&connection::handle_write, shared_from_this(), // asio::placeholders::error)); } asio::async_read(socket_, asio::buffer(buffer_, 4), boost::bind(&connection::handle_read_header, shared_from_this(), asio::placeholders::error, asio::placeholders::bytes_transferred)); } else if (e != asio::error::operation_aborted) { connection_manager_.stop(shared_from_this()); return; } }
void natpmp::on_reply(asio::error_code const& e , std::size_t bytes_transferred) { using namespace libtorrent::detail; if (e) return; try { if (m_remote != m_nat_endpoint) { m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) , m_remote, bind(&natpmp::on_reply, this, _1, _2)); return; } m_send_timer.cancel(); assert(m_currently_mapping >= 0); int i = m_currently_mapping; mapping& m = m_mappings[i]; char* in = m_response_buffer; int version = read_uint8(in); int cmd = read_uint8(in); int result = read_uint16(in); int time = read_uint32(in); int private_port = read_uint16(in); int public_port = read_uint16(in); int lifetime = read_uint32(in); (void)time; // to remove warning #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << time_now_string() << " <== port map response: " << (cmd - 128 == 1 ? "udp" : "tcp") << " local: " << private_port << " external: " << public_port << " ttl: " << lifetime << std::endl; #endif #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (version != 0) { m_log << "*** unexpected version: " << version << std::endl; } #endif #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (private_port != m.local_port) { m_log << "*** unexpected local port: " << private_port << std::endl; } #endif #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (cmd != 128 + m.protocol) { m_log << "*** unexpected protocol: " << (cmd - 128) << std::endl; } #endif if (public_port == 0 || lifetime == 0) { // this means the mapping was // successfully closed m.local_port = 0; } else { m.expires = time_now() + seconds(int(lifetime * 0.7f)); m.external_port = public_port; } if (result != 0) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << "*** ERROR: " << result << std::endl; #endif std::stringstream errmsg; errmsg << "NAT router reports error (" << result << ") "; switch (result) { case 1: errmsg << "Unsupported protocol version"; break; case 2: errmsg << "Not authorized to create port map (enable NAT-PMP on your router)"; break; case 3: errmsg << "Network failure"; break; case 4: errmsg << "Out of resources"; break; case 5: errmsg << "Unsupported opcode"; break; } throw std::runtime_error(errmsg.str()); } // don't report when we remove mappings if (m.local_port != 0) { int tcp_port = 0; int udp_port = 0; if (m.protocol == 1) udp_port = m.external_port; else tcp_port = public_port; m_callback(tcp_port, udp_port, ""); } } catch (std::exception& e) { // try again in two hours m_mappings[m_currently_mapping].expires = time_now() + hours(2); m_callback(0, 0, e.what()); } int i = m_currently_mapping; m_currently_mapping = -1; m_mappings[i].need_update = false; m_send_timer.cancel(); update_expiration_timer(); try_next_mapping(i); }
void connection::handle_read(const asio::error_code& e, std::size_t bytes_transferred) { if (!e) { if (bytes_transferred != size) { this->client_->m_main->consoleLogger->information(Poco::format("Did not receive proper amount of bytes : rcv: %?d needed: %?d", bytes_transferred, size)); server.stop(shared_from_this()); return; } //printf("uid("XI64")\n", uid); // read object size if ((size > MAXPACKETSIZE) || (size <= 0)) { //ERROR - object too large - close connection server.stop(shared_from_this()); return; } //TODO: Decision: have socket read thread handle packets, or push into a queue //socket thread (easy, already done) // PRO: typically instant response times due to it being processed as it comes in // CON: a large request (legit or non) would cause the socket read thread to lag // //process thread (complex, ideally better) // PRO: can alleviate lag on socket threads and create multiple thread processing queues depending on importance // CON: complexity and large requests would typically land in the same thread (causing even more lag for them) unless // made even more complex to have multiple threads for large requests // //Option 3: Evony style // -- create a process thread per x amount of sockets // PRO: lag from one client only affects a set amount of players and not the entire server // CON: quite complex. is ultimately the process thread option only for x amount of sockets // parse packet request_.size = size; amf3parser * cparser = new amf3parser(buffer_.data()); request_.object = cparser->ReadNextObject(); request_.connection = this; try { request_handler_.handle_request(request_, reply_); } catch (std::exception& e) { std::cerr << "handle_request() exception: " << e.what() << "\n"; } delete cparser; if (reply_.objects.size() > 0) { // send reply packets try { socket_.write_some(reply_.to_buffers()); } catch (std::exception& e) { std::cerr << "asio::write_some() exception: " << e.what() << "\n"; } reply_.objects.clear(); } asio::async_read(socket_, asio::buffer(buffer_, 4), boost::bind(&connection::handle_read_header, shared_from_this(), asio::placeholders::error, asio::placeholders::bytes_transferred)); } else if (e != asio::error::operation_aborted) { server.stop(shared_from_this()); return; } }