gearman_return_t error_code() const { return universal.error_code(); }
inline error_code make_error_code( windows_error_code e ) { return error_code( e, system_category() ); }
file_handle file_pool::open_file(void* st, std::string const& p , int file_index, file_storage const& fs, int m, error_code& ec) { // potentially used to hold a reference to a file object that's // about to be destructed. If we have such object we assign it to // this member to be destructed after we release the std::mutex. On some // operating systems (such as OSX) closing a file may take a long // time. We don't want to hold the std::mutex for that. file_handle defer_destruction; std::unique_lock<std::mutex> l(m_mutex); #if TORRENT_USE_ASSERTS // we're not allowed to open a file // from a deleted storage! TORRENT_ASSERT(std::find(m_deleted_storages.begin(), m_deleted_storages.end() , std::make_pair(fs.name(), static_cast<void const*>(&fs))) == m_deleted_storages.end()); #endif TORRENT_ASSERT(st != 0); TORRENT_ASSERT(is_complete(p)); TORRENT_ASSERT((m & file::rw_mask) == file::read_only || (m & file::rw_mask) == file::read_write); file_set::iterator i = m_files.find(std::make_pair(st, file_index)); if (i != m_files.end()) { lru_file_entry& e = i->second; e.last_use = aux::time_now(); if (e.key != st && ((e.mode & file::rw_mask) != file::read_only || (m & file::rw_mask) != file::read_only)) { // this means that another instance of the storage // is using the exact same file. ec = errors::file_collision; return file_handle(); } e.key = st; // if we asked for a file in write mode, // and the cached file is is not opened in // write mode, re-open it if ((((e.mode & file::rw_mask) != file::read_write) && ((m & file::rw_mask) == file::read_write)) || (e.mode & file::random_access) != (m & file::random_access)) { // close the file before we open it with // the new read/write privileges, since windows may // file opening a file twice. However, since there may // be outstanding operations on it, we can't close the // file, we can only delete our reference to it. // if this is the only reference to the file, it will be closed defer_destruction = e.file_ptr; e.file_ptr = boost::make_shared<file>(); std::string full_path = fs.file_path(file_index, p); if (!e.file_ptr->open(full_path, m, ec)) { m_files.erase(i); return file_handle(); } #ifdef TORRENT_WINDOWS if (m_low_prio_io) set_low_priority(e.file_ptr); #endif TORRENT_ASSERT(e.file_ptr->is_open()); e.mode = m; } return e.file_ptr; } lru_file_entry e; e.file_ptr = boost::make_shared<file>(); if (!e.file_ptr) { ec = error_code(boost::system::errc::not_enough_memory, generic_category()); return e.file_ptr; } std::string full_path = fs.file_path(file_index, p); if (!e.file_ptr->open(full_path, m, ec)) return file_handle(); #ifdef TORRENT_WINDOWS if (m_low_prio_io) set_low_priority(e.file_ptr); #endif e.mode = m; e.key = st; m_files.insert(std::make_pair(std::make_pair(st, file_index), e)); TORRENT_ASSERT(e.file_ptr->is_open()); file_handle file_ptr = e.file_ptr; // the file is not in our cache if (int(m_files.size()) >= m_size) { // the file cache is at its maximum size, close // the least recently used (lru) file from it remove_oldest(l); } return file_ptr; }
virtual void clear_error() { m_error = error_code(); m_error_file.resize(0); }
// explicit conversion: inline error_code make_error_code( errc_t e ) { return error_code( e, get_generic_category() ); }
void *memory_grow (void *memory, size_t size) { char *pointer; char *pointer_resized; size_t size_current; if (!memory) { error (InvalidArgument); return NULL; } if (size == 0) { error (InvalidArgument); return NULL; } size_current = memory_size (memory); if (size_current >= size) { error (InvalidOperation); return NULL; } if (!size_t_add (sizeof (size_t), size, NULL)) { error_code (Overflow, 1); return NULL; } LOCK (); if (!unsigned_long_long_add (size - size_current, commit_size, NULL)) { UNLOCK (); error_code (Overflow, 2); return NULL; } if (!unsigned_long_long_add (size - size_current, total_create_size, NULL)) { UNLOCK (); error_code (Overflow, 3); return NULL; } if (commit_limit != ULLONG_MAX) { if ((size - size_current) + commit_size > commit_limit) { UNLOCK (); error (MemoryCommitLimit); return NULL; } } if (total_create_limit != ULLONG_MAX) { if ((size - size_current) + total_create_size > total_create_limit) { UNLOCK (); error (MemoryTotalCreateLimit); return NULL; } } total_create_size += size - size_current; commit_size += size - size_current; UNLOCK (); pointer = memory; pointer = pointer - sizeof (size_t); if (!(pointer_resized = realloc (pointer, sizeof (size_t) + size))) { LOCK (); total_create_size -= size - size_current; commit_size -= size - size_current; UNLOCK (); error (OutOfMemory); return NULL; } set_size (pointer_resized, size); return pointer_resized + sizeof (size_t); }
error_code listen (int/* backlog */) { return error_code(); }
inline error_code make_error_code( linux_errno e ) { return error_code( e, get_system_category() ); }
void TestPeerLogicSyncClient::on_connect () { { // pre-handshake hook is optional on_pre_handshake (); if (failure (error ())) return ; } if (socket ().needs_handshake ()) { if (failure (socket ().handshake (to_handshake_type (get_role ()), error ()))) return; } { std::size_t const amount = boost::asio::write ( socket (), boost::asio::buffer ("hello", 5), error ()); if (failure (error ())) return; if (unexpected (amount == 5, error ())) return; } { char data [7]; size_t const amount = boost::asio::read ( socket (), boost::asio::buffer (data, 7), error ()); if (failure (error ())) return; if (unexpected (amount == 7, error ())) return; if (unexpected (memcmp (&data, "goodbye", 7) == 0, error ())) return; } // Wait for 1 byte which should never come. Instead, // the server should close its end and we will get eof { char data [1]; boost::asio::read (socket (), boost::asio::buffer (data, 1), error ()); if (error () == boost::asio::error::eof) { error () = error_code (); } else if (unexpected (failure (error ()), error ())) { return; } } if (socket ().needs_handshake ()) { if (failure (socket ().shutdown (error ()), true)) return; } if (failure (socket ().shutdown (Socket::shutdown_both, error ()))) return; if (failure (socket ().close (error ()))) return; }
void http_tracker_connection::parse(int status_code, lazy_entry const& e) { boost::shared_ptr<request_callback> cb = requester(); if (!cb) return; int interval = int(e.dict_find_int_value("interval", 0)); int min_interval = int(e.dict_find_int_value("min interval", 30)); // if no interval is specified, default to 30 minutes if (interval == 0) interval = 1800; std::string trackerid; lazy_entry const* tracker_id = e.dict_find_string("tracker id"); if (tracker_id) trackerid = tracker_id->string_value(); // parse the response lazy_entry const* failure = e.dict_find_string("failure reason"); if (failure) { fail(error_code(errors::tracker_failure), status_code , failure->string_value().c_str(), interval, min_interval); return; } lazy_entry const* warning = e.dict_find_string("warning message"); if (warning) cb->tracker_warning(tracker_req(), warning->string_value()); std::vector<peer_entry> peer_list; if (tracker_req().kind == tracker_request::scrape_request) { std::string ih = tracker_req().info_hash.to_string(); lazy_entry const* files = e.dict_find_dict("files"); if (files == 0) { fail(error_code(errors::invalid_files_entry), -1, "" , interval, min_interval); return; } lazy_entry const* scrape_data = files->dict_find_dict(ih.c_str()); if (scrape_data == 0) { fail(error_code(errors::invalid_hash_entry), -1, "" , interval, min_interval); return; } int complete = int(scrape_data->dict_find_int_value("complete", -1)); int incomplete = int(scrape_data->dict_find_int_value("incomplete", -1)); int downloaded = int(scrape_data->dict_find_int_value("downloaded", -1)); int downloaders = int(scrape_data->dict_find_int_value("downloaders", -1)); cb->tracker_scrape_response(tracker_req(), complete , incomplete, downloaded, downloaders); return; } lazy_entry const* peers_ent = e.dict_find("peers"); if (peers_ent && peers_ent->type() == lazy_entry::string_t) { char const* peers = peers_ent->string_ptr(); int len = peers_ent->string_length(); for (int i = 0; i < len; i += 6) { if (len - i < 6) break; peer_entry p; p.pid.clear(); error_code ec; p.ip = detail::read_v4_address(peers).to_string(ec); p.port = detail::read_uint16(peers); if (ec) continue; peer_list.push_back(p); } } else if (peers_ent && peers_ent->type() == lazy_entry::list_t) { int len = peers_ent->list_size(); for (int i = 0; i < len; ++i) { peer_entry p; if (!extract_peer_info(*peers_ent->list_at(i), p)) return; peer_list.push_back(p); } } else { peers_ent = 0; } #if TORRENT_USE_IPV6 lazy_entry const* ipv6_peers = e.dict_find_string("peers6"); if (ipv6_peers) { char const* peers = ipv6_peers->string_ptr(); int len = ipv6_peers->string_length(); for (int i = 0; i < len; i += 18) { if (len - i < 18) break; peer_entry p; p.pid.clear(); error_code ec; p.ip = detail::read_v6_address(peers).to_string(ec); p.port = detail::read_uint16(peers); if (ec) continue; peer_list.push_back(p); } } else { ipv6_peers = 0; } #else lazy_entry const* ipv6_peers = 0; #endif // if we didn't receive any peers. We don't care if we're stopping anyway if (peers_ent == 0 && ipv6_peers == 0 && tracker_req().event != tracker_request::stopped) { fail(error_code(errors::invalid_peers_entry), -1, "" , interval, min_interval); return; } // look for optional scrape info address external_ip; lazy_entry const* ip_ent = e.dict_find_string("external ip"); if (ip_ent) { char const* p = ip_ent->string_ptr(); if (ip_ent->string_length() == address_v4::bytes_type().size()) external_ip = detail::read_v4_address(p); #if TORRENT_USE_IPV6 else if (ip_ent->string_length() == address_v6::bytes_type().size()) external_ip = detail::read_v6_address(p); #endif } int complete = int(e.dict_find_int_value("complete", -1)); int incomplete = int(e.dict_find_int_value("incomplete", -1)); std::list<address> ip_list; if (m_tracker_connection) { error_code ec; ip_list.push_back(m_tracker_connection->socket().remote_endpoint(ec).address()); std::list<tcp::endpoint> const& epts = m_tracker_connection->endpoints(); for (std::list<tcp::endpoint>::const_iterator i = epts.begin() , end(epts.end()); i != end; ++i) { ip_list.push_back(i->address()); } } cb->tracker_response(tracker_req(), m_tracker_ip, ip_list, peer_list , interval, min_interval, complete, incomplete, external_ip, trackerid); }
void http_tracker_connection::start() { // TODO: authentication std::string url = tracker_req().url; if (tracker_req().kind == tracker_request::scrape_request) { // find and replace "announce" with "scrape" // in request std::size_t pos = url.find("announce"); if (pos == std::string::npos) { m_ios.post(boost::bind(&http_tracker_connection::fail_disp, self() , error_code(errors::scrape_not_available))); return; } url.replace(pos, 8, "scrape"); } #if TORRENT_USE_I2P bool i2p = is_i2p_url(url); #else static const bool i2p = false; #endif session_settings const& settings = m_ses.settings(); // if request-string already contains // some parameters, append an ampersand instead // of a question mark size_t arguments_start = url.find('?'); if (arguments_start != std::string::npos) url += "&"; else url += "?"; url += "info_hash="; url += escape_string((const char*)&tracker_req().info_hash[0], 20); if (tracker_req().kind == tracker_request::announce_request) { char str[1024]; const bool stats = tracker_req().send_stats; snprintf(str, sizeof(str), "&peer_id=%s&port=%d&uploaded=%" PRId64 "&downloaded=%" PRId64 "&left=%" PRId64 "&corrupt=%" PRId64 "&redundant=%" PRId64 "&compact=1&numwant=%d&key=%x&no_peer_id=1" , escape_string((const char*)&tracker_req().pid[0], 20).c_str() // the i2p tracker seems to verify that the port is not 0, // even though it ignores it otherwise , i2p ? 1 : tracker_req().listen_port , stats ? tracker_req().uploaded : 0 , stats ? tracker_req().downloaded : 0 , stats ? tracker_req().left : 0 , stats ? tracker_req().corrupt : 0 , stats ? tracker_req().redundant: 0 , tracker_req().num_want , tracker_req().key); url += str; #ifndef TORRENT_DISABLE_ENCRYPTION if (m_ses.get_pe_settings().in_enc_policy != pe_settings::disabled) url += "&supportcrypto=1"; #endif if (!tracker_req().trackerid.empty()) { std::string id = tracker_req().trackerid; url += "&trackerid="; url += escape_string(id.c_str(), id.length()); } if (tracker_req().event != tracker_request::none) { const char* event_string[] = {"completed", "started", "stopped", "paused"}; url += "&event="; url += event_string[tracker_req().event - 1]; } #if TORRENT_USE_I2P if (i2p) { url += "&ip="; url += escape_string(m_i2p_conn->local_endpoint().c_str() , m_i2p_conn->local_endpoint().size()); url += ".i2p"; } else #endif if (!m_ses.settings().anonymous_mode) { if (!settings.announce_ip.empty()) { url += "&ip=" + escape_string( settings.announce_ip.c_str(), settings.announce_ip.size()); } else if (m_ses.settings().announce_double_nat && is_local(m_ses.listen_address())) { // only use the global external listen address here // if it turned out to be on a local network // since otherwise the tracker should use our // source IP to determine our origin url += "&ip=" + print_address(m_ses.listen_address()); } if (!tracker_req().ipv6.empty() && !i2p) { url += "&ipv6="; url += tracker_req().ipv6; } if (!tracker_req().ipv4.empty() && !i2p) { url += "&ipv4="; url += tracker_req().ipv4; } } } m_tracker_connection.reset(new http_connection(m_ios, m_cc , boost::bind(&http_tracker_connection::on_response, self(), _1, _2, _3, _4) , true , boost::bind(&http_tracker_connection::on_connect, self(), _1) , boost::bind(&http_tracker_connection::on_filter, self(), _1, _2) #ifdef TORRENT_USE_OPENSSL , tracker_req().ssl_ctx #endif )); int timeout = tracker_req().event==tracker_request::stopped ?settings.stop_tracker_timeout :settings.tracker_completion_timeout; m_tracker_connection->get(url, seconds(timeout) , tracker_req().event == tracker_request::stopped ? 2 : 1 , &m_ps, 5, settings.anonymous_mode ? "" : settings.user_agent , bind_interface() #if TORRENT_USE_I2P , m_i2p_conn #endif ); // the url + 100 estimated header size sent_bytes(url.size() + 100); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) boost::shared_ptr<request_callback> cb = requester(); if (cb) { cb->debug_log("==> TRACKER_REQUEST [ url: %s ]", url.c_str()); } #endif }
void http_seed_connection::on_receive(error_code const& error , std::size_t bytes_transferred) { INVARIANT_CHECK; if (error) { m_statistics.received_bytes(0, bytes_transferred); #ifdef TORRENT_VERBOSE_LOGGING peer_log("*** http_seed_connection error: %s", error.message().c_str()); #endif return; } boost::shared_ptr<torrent> t = associated_torrent().lock(); TORRENT_ASSERT(t); for (;;) { buffer::const_interval recv_buffer = receive_buffer(); if (bytes_transferred == 0) break; TORRENT_ASSERT(recv_buffer.left() > 0); TORRENT_ASSERT(!m_requests.empty()); if (m_requests.empty()) { m_statistics.received_bytes(0, bytes_transferred); disconnect(errors::http_error, 2); return; } peer_request front_request = m_requests.front(); bool header_finished = m_parser.header_finished(); if (!header_finished) { bool parse_error = false; int protocol = 0; int payload = 0; boost::tie(payload, protocol) = m_parser.incoming(recv_buffer, parse_error); m_statistics.received_bytes(0, protocol); bytes_transferred -= protocol; #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS if (payload > front_request.length) payload = front_request.length; #endif if (parse_error) { m_statistics.received_bytes(0, bytes_transferred); disconnect(errors::http_parse_error, 2); return; } TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H'); TORRENT_ASSERT(recv_buffer.left() <= packet_size()); // this means the entire status line hasn't been received yet if (m_parser.status_code() == -1) { TORRENT_ASSERT(payload == 0); TORRENT_ASSERT(bytes_transferred == 0); break; } // if the status code is not one of the accepted ones, abort if (!is_ok_status(m_parser.status_code())) { int retry_time = atoi(m_parser.header("retry-after").c_str()); if (retry_time <= 0) retry_time = 5 * 60; // temporarily unavailable, retry later t->retry_web_seed(this, retry_time); std::string error_msg = to_string(m_parser.status_code()).elems + (" " + m_parser.message()); if (m_ses.m_alerts.should_post<url_seed_alert>()) { m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url() , error_msg)); } m_statistics.received_bytes(0, bytes_transferred); disconnect(error_code(m_parser.status_code(), get_http_category()), 1); return; } if (!m_parser.header_finished()) { TORRENT_ASSERT(payload == 0); TORRENT_ASSERT(bytes_transferred == 0); break; } } // we just completed reading the header if (!header_finished) { if (is_redirect(m_parser.status_code())) { // this means we got a redirection request // look for the location header std::string location = m_parser.header("location"); m_statistics.received_bytes(0, bytes_transferred); if (location.empty()) { // we should not try this server again. t->remove_web_seed(this); disconnect(errors::missing_location, 2); return; } // add the redirected url and remove the current one t->add_web_seed(location, web_seed_entry::http_seed); t->remove_web_seed(this); disconnect(errors::redirecting, 2); return; } std::string const& server_version = m_parser.header("server"); if (!server_version.empty()) { m_server_string = "URL seed @ "; m_server_string += m_host; m_server_string += " ("; m_server_string += server_version; m_server_string += ")"; } m_response_left = atol(m_parser.header("content-length").c_str()); if (m_response_left == -1) { m_statistics.received_bytes(0, bytes_transferred); // we should not try this server again. t->remove_web_seed(this); disconnect(errors::no_content_length, 2); return; } if (m_response_left != front_request.length) { m_statistics.received_bytes(0, bytes_transferred); // we should not try this server again. t->remove_web_seed(this); disconnect(errors::invalid_range, 2); return; } m_body_start = m_parser.body_start(); } recv_buffer.begin += m_body_start; // ========================= // === CHUNKED ENCODING === // ========================= while (m_parser.chunked_encoding() && m_chunk_pos >= 0 && m_chunk_pos < recv_buffer.left()) { int header_size = 0; size_type chunk_size = 0; buffer::const_interval chunk_start = recv_buffer; chunk_start.begin += m_chunk_pos; TORRENT_ASSERT(chunk_start.begin[0] == '\r' || is_hex(chunk_start.begin, 1)); bool ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size); if (!ret) { TORRENT_ASSERT(bytes_transferred >= size_t(chunk_start.left() - m_partial_chunk_header)); bytes_transferred -= chunk_start.left() - m_partial_chunk_header; m_statistics.received_bytes(0, chunk_start.left() - m_partial_chunk_header); m_partial_chunk_header = chunk_start.left(); if (bytes_transferred == 0) return; break; } else { #ifdef TORRENT_VERBOSE_LOGGING peer_log("*** parsed chunk: %d header_size: %d", chunk_size, header_size); #endif TORRENT_ASSERT(bytes_transferred >= size_t(header_size - m_partial_chunk_header)); bytes_transferred -= header_size - m_partial_chunk_header; m_statistics.received_bytes(0, header_size - m_partial_chunk_header); m_partial_chunk_header = 0; TORRENT_ASSERT(chunk_size != 0 || chunk_start.left() <= header_size || chunk_start.begin[header_size] == 'H'); // cut out the chunk header from the receive buffer TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX); cut_receive_buffer(header_size, t->block_size() + 1024, int(m_chunk_pos + m_body_start)); recv_buffer = receive_buffer(); recv_buffer.begin += m_body_start; m_chunk_pos += chunk_size; if (chunk_size == 0) { TORRENT_ASSERT(receive_buffer().left() < m_chunk_pos + m_body_start + 1 || receive_buffer()[int(m_chunk_pos + m_body_start)] == 'H' || (m_parser.chunked_encoding() && receive_buffer()[int(m_chunk_pos + m_body_start)] == '\r')); m_chunk_pos = -1; } } } int payload = bytes_transferred; if (payload > m_response_left) payload = int(m_response_left); if (payload > front_request.length) payload = front_request.length; m_statistics.received_bytes(payload, 0); incoming_piece_fragment(payload); m_response_left -= payload; if (m_parser.status_code() == 503) { if (!m_parser.finished()) return; int retry_time = atol(std::string(recv_buffer.begin, recv_buffer.end).c_str()); if (retry_time <= 0) retry_time = 60; #ifdef TORRENT_VERBOSE_LOGGING peer_log("*** retrying in %d seconds", retry_time); #endif m_statistics.received_bytes(0, bytes_transferred); // temporarily unavailable, retry later t->retry_web_seed(this, retry_time); disconnect(error_code(m_parser.status_code(), get_http_category()), 1); return; } // we only received the header, no data if (recv_buffer.left() == 0) break; if (recv_buffer.left() < front_request.length) break; // if the response is chunked, we need to receive the last // terminating chunk and the tail headers before we can proceed if (m_parser.chunked_encoding() && m_chunk_pos >= 0) break; m_requests.pop_front(); incoming_piece(front_request, recv_buffer.begin); if (associated_torrent().expired()) return; int size_to_cut = m_body_start + front_request.length; TORRENT_ASSERT(receive_buffer().left() < size_to_cut + 1 || receive_buffer()[size_to_cut] == 'H' || (m_parser.chunked_encoding() && receive_buffer()[size_to_cut] == '\r')); cut_receive_buffer(size_to_cut, t->block_size() + 1024); if (m_response_left == 0) m_chunk_pos = 0; else m_chunk_pos -= front_request.length; bytes_transferred -= payload; m_body_start = 0; if (m_response_left > 0) continue; TORRENT_ASSERT(m_response_left == 0); m_parser.reset(); } }
void clear_error() { m_error = error_code(); m_error_file.clear(); }
address bind_to_device(io_service& ios, Socket& sock , bool ipv4, char const* device_name, int port, error_code& ec) { tcp::endpoint bind_ep(address_v4::any(), port); address ip = address::from_string(device_name, ec); if (!ec) { #if TORRENT_USE_IPV6 // this is to cover the case where "0.0.0.0" is considered any IPv4 or // IPv6 address. If we're asking to be bound to an IPv6 address and // providing 0.0.0.0 as the device, turn it into "::0" if (ip == address_v4::any() && !ipv4) ip = address_v6::any(); #endif bind_ep.address(ip); // it appears to be an IP. Just bind to that address sock.bind(bind_ep, ec); return bind_ep.address(); } ec.clear(); #ifdef SO_BINDTODEVICE // try to use SO_BINDTODEVICE here, if that exists. If it fails, // fall back to the mechanism we have below sock.set_option(bind_to_device_opt(device_name), ec); if (ec) #endif { ec.clear(); // TODO: 2 this could be done more efficiently by just looking up // the interface with the given name, maybe even with if_nametoindex() std::vector<ip_interface> ifs = enum_net_interfaces(ios, ec); if (ec) return bind_ep.address(); bool found = false; for (int i = 0; i < int(ifs.size()); ++i) { // we're looking for a specific interface, and its address // (which must be of the same family as the address we're // connecting to) if (strcmp(ifs[i].name, device_name) != 0) continue; if (ifs[i].interface_address.is_v4() != ipv4) continue; bind_ep.address(ifs[i].interface_address); found = true; break; } if (!found) { ec = error_code(boost::system::errc::no_such_device, generic_category()); return bind_ep.address(); } } sock.bind(bind_ep, ec); return bind_ep.address(); }
bool has_error() const { return error_code() != CASS_OK; }
file_handle file_pool::open_file(storage_index_t st, std::string const& p , file_index_t const file_index, file_storage const& fs, int m, error_code& ec) { // potentially used to hold a reference to a file object that's // about to be destructed. If we have such object we assign it to // this member to be destructed after we release the std::mutex. On some // operating systems (such as OSX) closing a file may take a long // time. We don't want to hold the std::mutex for that. file_handle defer_destruction; std::unique_lock<std::mutex> l(m_mutex); #if TORRENT_USE_ASSERTS // we're not allowed to open a file // from a deleted storage! TORRENT_ASSERT(std::find(m_deleted_storages.begin(), m_deleted_storages.end() , std::make_pair(fs.name(), static_cast<void const*>(&fs))) == m_deleted_storages.end()); #endif TORRENT_ASSERT(is_complete(p)); TORRENT_ASSERT((m & file::rw_mask) == file::read_only || (m & file::rw_mask) == file::read_write); auto const i = m_files.find(std::make_pair(st, file_index)); if (i != m_files.end()) { lru_file_entry& e = i->second; e.last_use = aux::time_now(); // if we asked for a file in write mode, // and the cached file is is not opened in // write mode, re-open it if ((((e.mode & file::rw_mask) != file::read_write) && ((m & file::rw_mask) == file::read_write)) || (e.mode & file::random_access) != (m & file::random_access)) { file_handle new_file = std::make_shared<file>(); std::string full_path = fs.file_path(file_index, p); if (!new_file->open(full_path, m, ec)) return file_handle(); #ifdef TORRENT_WINDOWS if (m_low_prio_io) set_low_priority(new_file); #endif TORRENT_ASSERT(new_file->is_open()); defer_destruction = std::move(e.file_ptr); e.file_ptr = std::move(new_file); e.mode = m; } return e.file_ptr; } lru_file_entry e; e.file_ptr = std::make_shared<file>(); if (!e.file_ptr) { ec = error_code(boost::system::errc::not_enough_memory, generic_category()); return file_handle(); } std::string full_path = fs.file_path(file_index, p); if (!e.file_ptr->open(full_path, m, ec)) return file_handle(); #ifdef TORRENT_WINDOWS if (m_low_prio_io) set_low_priority(e.file_ptr); #endif e.mode = m; file_handle file_ptr = e.file_ptr; m_files.insert(std::make_pair(std::make_pair(st, file_index), e)); TORRENT_ASSERT(file_ptr->is_open()); if (int(m_files.size()) >= m_size) { // the file cache is at its maximum size, close // the least recently used (lru) file from it remove_oldest(l); } return file_ptr; }
void HTTPCallbackTcpConnection::start() { httpMessage.clear(); handleHttpRequest(error_code(), 0); }
void do_async_handshake(handshake_type, HandshakeHandler handler) { get_io_service().post(bind(handler, error_code())); }
inline error_code make_error_code( cygwin_errno e ) { return error_code( e, system_category() ); }
error_code do_handshake(handshake_type, error_code &ec) { return ec = error_code(); }
error_code listen (int backlog) { return (::listen(_fd, backlog) != 0) ? get_last_system_error() : error_code(); }
/// This is where the link is actually performed. bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) { // Honor -mllvm if (!context.llvmOptions().empty()) { unsigned numArgs = context.llvmOptions().size(); const char **args = new const char *[numArgs + 2]; args[0] = "lld (LLVM option parsing)"; for (unsigned i = 0; i != numArgs; ++i) args[i + 1] = context.llvmOptions()[i]; args[numArgs + 1] = 0; llvm::cl::ParseCommandLineOptions(numArgs + 1, args); } InputGraph &inputGraph = context.inputGraph(); if (!inputGraph.numFiles()) return false; // Read inputs ScopedTask readTask(getDefaultDomain(), "Read Args"); std::vector<std::vector<std::unique_ptr<File> > > files( inputGraph.numFiles()); size_t index = 0; std::atomic<bool> fail(false); TaskGroup tg; std::vector<std::unique_ptr<LinkerInput> > linkerInputs; for (auto &ie : inputGraph.inputElements()) { if (ie->kind() == InputElement::Kind::File) { FileNode *fileNode = (llvm::dyn_cast<FileNode>)(ie.get()); auto linkerInput = fileNode->createLinkerInput(context); if (!linkerInput) { llvm::outs() << fileNode->errStr(error_code(linkerInput)) << "\n"; return false; } linkerInputs.push_back(std::move(*linkerInput)); } else { llvm_unreachable("Not handling other types of InputElements"); } } for (const auto &input : linkerInputs) { if (context.logInputFiles()) llvm::outs() << input->getUserPath() << "\n"; tg.spawn([ &, index]{ if (error_code ec = context.parseFile(*input, files[index])) { diagnostics << "Failed to read file: " << input->getUserPath() << ": " << ec.message() << "\n"; fail = true; return; } }); ++index; } tg.sync(); readTask.end(); if (fail) return false; InputFiles inputs; for (auto &f : inputGraph.internalFiles()) inputs.appendFile(*f.get()); for (auto &f : files) inputs.appendFiles(f); // Give target a chance to add files. context.addImplicitFiles(inputs); // assign an ordinal to each file so sort() can preserve command line order inputs.assignFileOrdinals(); // Do core linking. ScopedTask resolveTask(getDefaultDomain(), "Resolve"); Resolver resolver(context, inputs); if (resolver.resolve()) { if (!context.allowRemainingUndefines()) return false; } MutableFile &merged = resolver.resultFile(); resolveTask.end(); // Run passes on linked atoms. ScopedTask passTask(getDefaultDomain(), "Passes"); PassManager pm; context.addPasses(pm); pm.runOnFile(merged); passTask.end(); // Give linked atoms to Writer to generate output file. ScopedTask writeTask(getDefaultDomain(), "Write"); if (error_code ec = context.writeFile(merged)) { diagnostics << "Failed to write file '" << context.outputPath() << "': " << ec.message() << "\n"; return false; } return true; }
boost::intrusive_ptr<file> file_pool::open_file(void* st, std::string const& p , file_storage::iterator fe, file_storage const& fs, int m, error_code& ec) { TORRENT_ASSERT(st != 0); TORRENT_ASSERT(is_complete(p)); TORRENT_ASSERT((m & file::rw_mask) == file::read_only || (m & file::rw_mask) == file::read_write); mutex::scoped_lock l(m_mutex); file_set::iterator i = m_files.find(std::make_pair(st, fs.file_index(*fe))); if (i != m_files.end()) { lru_file_entry& e = i->second; e.last_use = time_now(); if (e.key != st && ((e.mode & file::rw_mask) != file::read_only || (m & file::rw_mask) != file::read_only)) { // this means that another instance of the storage // is using the exact same file. #if BOOST_VERSION >= 103500 ec = errors::file_collision; #endif return boost::intrusive_ptr<file>(); } e.key = st; // if we asked for a file in write mode, // and the cached file is is not opened in // write mode, re-open it if ((((e.mode & file::rw_mask) != file::read_write) && ((m & file::rw_mask) == file::read_write)) || (e.mode & file::no_buffer) != (m & file::no_buffer) || (e.mode & file::random_access) != (m & file::random_access)) { // close the file before we open it with // the new read/write privilages TORRENT_ASSERT(e.file_ptr->refcount() == 1); #if TORRENT_CLOSE_MAY_BLOCK mutex::scoped_lock l(m_closer_mutex); m_queued_for_close.push_back(e.file_ptr); l.unlock(); e.file_ptr = new file; #else e.file_ptr->close(); #endif std::string full_path = combine_path(p, fs.file_path(*fe)); if (!e.file_ptr->open(full_path, m, ec)) { m_files.erase(i); return boost::intrusive_ptr<file>(); } #ifdef TORRENT_WINDOWS // file prio is supported on vista and up #if _WIN32_WINNT >= 0x0600 if (m_low_prio_io) { // TODO: load this function dynamically from Kernel32.dll FILE_IO_PRIORITY_HINT_INFO priorityHint; priorityHint.PriorityHint = IoPriorityHintLow; SetFileInformationByHandle(e.file_ptr->native_handle(), FileIoPriorityHintInfo, &priorityHint, sizeof(PriorityHint)); } #endif #endif TORRENT_ASSERT(e.file_ptr->is_open()); e.mode = m; } TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer)); return e.file_ptr; } // the file is not in our cache if ((int)m_files.size() >= m_size) { // the file cache is at its maximum size, close // the least recently used (lru) file from it remove_oldest(); } lru_file_entry e; e.file_ptr.reset(new (std::nothrow)file); if (!e.file_ptr) { ec = error_code(ENOMEM, get_posix_category()); return e.file_ptr; } std::string full_path = combine_path(p, fs.file_path(*fe)); if (!e.file_ptr->open(full_path, m, ec)) return boost::intrusive_ptr<file>(); e.mode = m; e.key = st; m_files.insert(std::make_pair(std::make_pair(st, fs.file_index(*fe)), e)); TORRENT_ASSERT(e.file_ptr->is_open()); return e.file_ptr; }
void http_tracker_connection::on_response(error_code const& ec , http_parser const& parser, char const* data, int size) { // keep this alive boost::shared_ptr<http_tracker_connection> me(shared_from_this()); if (ec && ec != boost::asio::error::eof) { fail(ec); return; } if (!parser.header_finished()) { fail(boost::asio::error::eof); return; } if (parser.status_code() != 200) { fail(error_code(parser.status_code(), get_http_category()) , parser.status_code(), parser.message().c_str()); return; } if (ec && ec != boost::asio::error::eof) { fail(ec, parser.status_code()); return; } received_bytes(size + parser.body_start()); // handle tracker response error_code ecode; boost::shared_ptr<request_callback> cb = requester(); if (!cb) { close(); return; } tracker_response resp = parse_tracker_response(data, size, ecode , tracker_req().kind, tracker_req().info_hash); if (!resp.warning_message.empty()) cb->tracker_warning(tracker_req(), resp.warning_message); if (ecode) { fail(ecode, parser.status_code(), resp.failure_reason.c_str() , resp.interval, resp.min_interval); close(); return; } // do slightly different things for scrape requests if (0 != (tracker_req().kind & tracker_request::scrape_request)) { cb->tracker_scrape_response(tracker_req(), resp.complete , resp.incomplete, resp.downloaded, resp.downloaders); } else { std::list<address> ip_list; if (m_tracker_connection) { error_code ignore; std::vector<tcp::endpoint> const& epts = m_tracker_connection->endpoints(); for (std::vector<tcp::endpoint>::const_iterator i = epts.begin() , end(epts.end()); i != end; ++i) { ip_list.push_back(i->address()); } } cb->tracker_response(tracker_req(), m_tracker_ip, ip_list, resp); } close(); }
// 压入待解析数据 void parse(char const* data, std::size_t size) { char const* buf = data; std::size_t len = size; while (len) { if (0 == pos_) { // 缓冲区中无数据, 直接在上层缓冲区中尝试组包. if (len < head_size) { // 不足一个封包头, 写入缓冲区即可 write_buffer(buf, len); return ; } else { // 有完整的封包头, 进一步检测是否有完整的封包. std::size_t packet_len = Sizer()(packethead(buf)) + head_size; if (packet_len > size_) { // 封包长错误 invoke_callback(generate_error(bee::parse_error), 0, 0, 0); return ; } if (len < packet_len) { // 不足一个封包, 放入缓冲区中, 等待后续数据. write_buffer(buf, len); return ; } else { // 有完整的封包, 直接处理. invoke_callback(error_code(), &packethead(buf), buf + head_size, packet_len - head_size); buf += packet_len; len -= packet_len; continue; } } } else if (pos_ < head_size) { // 缓冲区中有数据, 但不足一个封包头, 尝试拼足一个封包头 std::size_t delta = head_size - pos_; std::size_t cpy_size = (std::min)(delta, len); write_buffer(buf, cpy_size); buf += cpy_size; len -= cpy_size; continue; } else { // 缓冲区中有完整的封包头 std::size_t packet_len = Sizer()(packethead(buf_)) + head_size; if (packet_len > size_) { // 封包长错误 invoke_callback(generate_error(bee::parse_error), 0, 0, 0); return ; } std::size_t delta = packet_len - pos_; if (delta > len) { // 无法拼出一个完整的封包 write_buffer(buf, len); return ; } else { // 可以拼出一个完整的封包 write_buffer(buf, delta); invoke_callback(error_code(), &packethead(buf_), buf_ + head_size, pos_ - head_size); pos_ = 0; buf += delta; len -= delta; continue; } } } }
void http_tracker_connection::start() { std::string url = tracker_req().url; if (0 != (tracker_req().kind & tracker_request::scrape_request)) { // find and replace "announce" with "scrape" // in request std::size_t pos = url.find("announce"); if (pos == std::string::npos) { tracker_connection::fail(error_code(errors::scrape_not_available)); return; } url.replace(pos, 8, "scrape"); } #if TORRENT_USE_I2P bool i2p = is_i2p_url(url); #else static const bool i2p = false; #endif aux::session_settings const& settings = m_man.settings(); // if request-string already contains // some parameters, append an ampersand instead // of a question mark size_t arguments_start = url.find('?'); if (arguments_start != std::string::npos) url += "&"; else url += "?"; url += "info_hash="; url += escape_string(tracker_req().info_hash.data(), 20); if (0 == (tracker_req().kind & tracker_request::scrape_request)) { const char* event_string[] = {"completed", "started", "stopped", "paused"}; char str[1024]; const bool stats = tracker_req().send_stats; snprintf(str, sizeof(str) , "&peer_id=%s" "&port=%d" "&uploaded=%" PRId64 "&downloaded=%" PRId64 "&left=%" PRId64 "&corrupt=%" PRId64 "&key=%08X" "%s%s" // event "&numwant=%d" "&compact=1" "&no_peer_id=1" , escape_string(tracker_req().pid.data(), 20).c_str() // the i2p tracker seems to verify that the port is not 0, // even though it ignores it otherwise , i2p ? 1 : tracker_req().listen_port , stats ? tracker_req().uploaded : 0 , stats ? tracker_req().downloaded : 0 , stats ? tracker_req().left : 0 , stats ? tracker_req().corrupt : 0 , tracker_req().key , (tracker_req().event != tracker_request::none) ? "&event=" : "" , (tracker_req().event != tracker_request::none) ? event_string[tracker_req().event - 1] : "" , tracker_req().num_want); url += str; #if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS) if (settings.get_int(settings_pack::in_enc_policy) != settings_pack::pe_disabled && settings.get_bool(settings_pack::announce_crypto_support)) url += "&supportcrypto=1"; #endif if (stats && settings.get_bool(settings_pack::report_redundant_bytes)) { url += "&redundant="; url += to_string(tracker_req().redundant).elems; } if (!tracker_req().trackerid.empty()) { std::string id = tracker_req().trackerid; url += "&trackerid="; url += escape_string(id.c_str(), id.length()); } #if TORRENT_USE_I2P if (i2p && tracker_req().i2pconn) { if (tracker_req().i2pconn->local_endpoint().empty()) { fail(error_code(errors::no_i2p_endpoint), -1, "Waiting for i2p acceptor from SAM bridge", 5); return; } else { url += "&ip=" + tracker_req ().i2pconn->local_endpoint () + ".i2p"; } } else #endif if (!settings.get_bool(settings_pack::anonymous_mode)) { std::string announce_ip = settings.get_str(settings_pack::announce_ip); if (!announce_ip.empty()) { url += "&ip=" + escape_string(announce_ip.c_str(), announce_ip.size()); } // TODO: support this somehow /* else if (settings.get_bool(settings_pack::announce_double_nat) && is_local(m_ses.listen_address())) { // only use the global external listen address here // if it turned out to be on a local network // since otherwise the tracker should use our // source IP to determine our origin url += "&ip=" + print_address(m_ses.listen_address()); } */ } } m_tracker_connection.reset(new http_connection(get_io_service(), m_man.host_resolver() , boost::bind(&http_tracker_connection::on_response, shared_from_this(), _1, _2, _3, _4) , true, settings.get_int(settings_pack::max_http_recv_buffer_size) , boost::bind(&http_tracker_connection::on_connect, shared_from_this(), _1) , boost::bind(&http_tracker_connection::on_filter, shared_from_this(), _1, _2) #ifdef TORRENT_USE_OPENSSL , tracker_req().ssl_ctx #endif )); int timeout = tracker_req().event==tracker_request::stopped ?settings.get_int(settings_pack::stop_tracker_timeout) :settings.get_int(settings_pack::tracker_completion_timeout); // when sending stopped requests, prefer the cached DNS entry // to avoid being blocked for slow or failing responses. Chances // are that we're shutting down, and this should be a best-effort // attempt. It's not worth stalling shutdown. aux::proxy_settings ps(settings); m_tracker_connection->get(url, seconds(timeout) , tracker_req().event == tracker_request::stopped ? 2 : 1 , ps.proxy_tracker_connections ? &ps : NULL , 5, settings.get_bool(settings_pack::anonymous_mode) ? "" : settings.get_str(settings_pack::user_agent) , bind_interface() , tracker_req().event == tracker_request::stopped ? resolver_interface::prefer_cache : resolver_interface::abort_on_shutdown , tracker_req().auth #if TORRENT_USE_I2P , tracker_req().i2pconn #endif ); // the url + 100 estimated header size sent_bytes(url.size() + 100); #ifndef TORRENT_DISABLE_LOGGING boost::shared_ptr<request_callback> cb = requester(); if (cb) { cb->debug_log("==> TRACKER_REQUEST [ url: %s ]", url.c_str()); } #endif }
static bool argument_named (int argc, char **argv, int *argi, AppArgument *arguments) { size_t i, digits; for (i = 0; arguments[i].type != AppArgumentTypeEnd; i++) { if (arguments[i].type != AppArgumentTypeNamed) { continue; } if (!((arguments[i].object.named.short_form && string_equals (argv[*argi], arguments[i].object.named.short_form)) || (arguments[i].object.named.long_form && string_equals (argv[*argi], arguments[i].object.named.long_form)))) { continue; } if (arguments[i].have_value) { print ("The argument "); app_arguments_print_named_form (arguments[i]); print (" is duplicated.\n"); error (AppArgumentDuplicate); return false; } switch (arguments[i].value_type) { case AppArgumentBoolean: *arguments[i].value.boolean = !arguments[i].value_default.boolean; arguments[i].have_value = true; *argi += 1; return true; case AppArgumentInteger: if (*argi + 1 == argc) { print ("The argument "); app_arguments_print_named_form (arguments[i]); print (" is missing an integer value.\n"); error (AppArgumentMissingIntegerValue); return false; } if (!convert_string_to_int (argv[*argi + 1], arguments[i].value.integer, &digits)) { print ("The value '%s' for ", argv[*argi + 1]); app_arguments_print_named_form (arguments[i]); print (" could not be converted to an integer value.\n"); error_code (FunctionCall, 1); return false; } if (digits != string_length (argv[*argi + 1])) { print ("The value '%s' for ", argv[*argi + 1]); app_arguments_print_named_form (arguments[i]); print (" could not be converted to an integer value.\n"); error (AppArgumentInvalidIntegerValue); return false; } arguments[i].have_value = true; *argi += 2; return true; case AppArgumentUInt64: if (*argi + 1 == argc) { print ("The argument "); app_arguments_print_named_form (arguments[i]); print (" is missing an UInt64 value.\n"); error (AppArgumentMissingUInt64Value); return false; } if (!convert_string_to_unsigned_long_long (argv[*argi + 1], (unsigned long long *)arguments[i].value.uint64, &digits)) { print ("The value '%s' for ", argv[*argi + 1]); app_arguments_print_named_form (arguments[i]); print (" could not be converted to an UInt64 value.\n"); error_code (FunctionCall, 2); return false; } if (digits != string_length (argv[*argi + 1])) { print ("The value '%s' for ", argv[*argi + 1]); app_arguments_print_named_form (arguments[i]); print (" could not be converted to an UInt64 value.\n"); error (AppArgumentInvalidUInt64Value); return false; } arguments[i].have_value = true; *argi += 2; return true; case AppArgumentString: if (*argi + 1 == argc) { print ("The argument "); app_arguments_print_named_form (arguments[i]); print (" is missing a string value.\n"); error (AppArgumentMissingStringValue); return false; } *arguments[i].value.string = argv[*argi + 1]; arguments[i].have_value = true; *argi += 2; return true; } } print ("Unrecognized argument '%s'.\n", argv[*argi]); error (AppArgumentUnknownNamedArgument); return false; }
void set_error(error_code& ec, int e) { ec = error_code(e, asio::error::get_system_category()); }
std::vector<ip_interface> enum_net_interfaces(io_service& ios, error_code& ec) { TORRENT_UNUSED(ios); // this may be unused depending on configuration std::vector<ip_interface> ret; #if defined TORRENT_BUILD_SIMULATOR TORRENT_UNUSED(ec); ip_interface wan; wan.interface_address = ios.get_ip(); wan.netmask = address_v4::from_string("255.255.255.255"); strcpy(wan.name, "eth0"); wan.mtu = ios.sim().config().path_mtu(ios.get_ip(), ios.get_ip()); ret.push_back(wan); #elif TORRENT_USE_IFADDRS int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { ec = error_code(errno, boost::asio::error::system_category); return ret; } ifaddrs *ifaddr; if (getifaddrs(&ifaddr) == -1) { ec = error_code(errno, boost::asio::error::system_category); close(s); return ret; } for (ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr == 0) continue; if ((ifa->ifa_flags & IFF_UP) == 0) continue; int family = ifa->ifa_addr->sa_family; if (family == AF_INET #if TORRENT_USE_IPV6 || family == AF_INET6 #endif ) { ip_interface iface; if (iface_from_ifaddrs(ifa, iface)) { ifreq req; memset(&req, 0, sizeof(req)); // -1 to leave a null terminator strncpy(req.ifr_name, iface.name, IF_NAMESIZE - 1); if (ioctl(s, siocgifmtu, &req) < 0) { continue; } iface.mtu = req.ifr_mtu; ret.push_back(iface); } } } close(s); freeifaddrs(ifaddr); // MacOS X, BSD and solaris #elif TORRENT_USE_IFCONF int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { ec = error_code(errno, boost::asio::error::system_category); return ret; } ifconf ifc; // make sure the buffer is aligned to hold ifreq structs ifreq buf[40]; ifc.ifc_len = sizeof(buf); ifc.ifc_buf = (char*)buf; if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { ec = error_code(errno, boost::asio::error::system_category); close(s); return ret; } char *ifr = (char*)ifc.ifc_req; int remaining = ifc.ifc_len; while (remaining > 0) { ifreq const& item = *reinterpret_cast<ifreq*>(ifr); #ifdef _SIZEOF_ADDR_IFREQ int current_size = _SIZEOF_ADDR_IFREQ(item); #elif defined TORRENT_BSD int current_size = item.ifr_addr.sa_len + IFNAMSIZ; #else int current_size = sizeof(ifreq); #endif if (remaining < current_size) break; if (item.ifr_addr.sa_family == AF_INET #if TORRENT_USE_IPV6 || item.ifr_addr.sa_family == AF_INET6 #endif ) { ip_interface iface; iface.interface_address = sockaddr_to_address(&item.ifr_addr); strcpy(iface.name, item.ifr_name); ifreq req; memset(&req, 0, sizeof(req)); // -1 to leave a null terminator strncpy(req.ifr_name, item.ifr_name, IF_NAMESIZE - 1); if (ioctl(s, siocgifmtu, &req) < 0) { ec = error_code(errno, boost::asio::error::system_category); close(s); return ret; } #ifndef TORRENT_OS2 iface.mtu = req.ifr_mtu; #else iface.mtu = req.ifr_metric; // according to tcp/ip reference #endif memset(&req, 0, sizeof(req)); strncpy(req.ifr_name, item.ifr_name, IF_NAMESIZE - 1); if (ioctl(s, SIOCGIFNETMASK, &req) < 0) { #if TORRENT_USE_IPV6 if (iface.interface_address.is_v6()) { // this is expected to fail (at least on MacOS X) iface.netmask = address_v6::any(); } else #endif { ec = error_code(errno, boost::asio::error::system_category); close(s); return ret; } } else { iface.netmask = sockaddr_to_address(&req.ifr_addr, item.ifr_addr.sa_family); } ret.push_back(iface); } ifr += current_size; remaining -= current_size; } close(s); #elif TORRENT_USE_GETADAPTERSADDRESSES #if _WIN32_WINNT >= 0x0501 // Load Iphlpapi library HMODULE iphlp = LoadLibraryA("Iphlpapi.dll"); if (iphlp) { // Get GetAdaptersAddresses() pointer typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG); GetAdaptersAddresses_t GetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress( iphlp, "GetAdaptersAddresses"); if (GetAdaptersAddresses) { PIP_ADAPTER_ADDRESSES adapter_addresses = 0; ULONG out_buf_size = 0; if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST, NULL, adapter_addresses, &out_buf_size) != ERROR_BUFFER_OVERFLOW) { FreeLibrary(iphlp); ec = boost::asio::error::operation_not_supported; return std::vector<ip_interface>(); } adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(out_buf_size); if (!adapter_addresses) { FreeLibrary(iphlp); ec = boost::asio::error::no_memory; return std::vector<ip_interface>(); } if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST, NULL, adapter_addresses, &out_buf_size) == NO_ERROR) { for (PIP_ADAPTER_ADDRESSES adapter = adapter_addresses; adapter != 0; adapter = adapter->Next) { ip_interface r; strncpy(r.name, adapter->AdapterName, sizeof(r.name)); r.name[sizeof(r.name)-1] = 0; r.mtu = adapter->Mtu; IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress; while (unicast) { r.interface_address = sockaddr_to_address(unicast->Address.lpSockaddr); ret.push_back(r); unicast = unicast->Next; } } } // Free memory free(adapter_addresses); FreeLibrary(iphlp); return ret; } FreeLibrary(iphlp); } #endif SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); if (s == SOCKET_ERROR) { ec = error_code(WSAGetLastError(), boost::asio::error::system_category); return ret; } INTERFACE_INFO buffer[30]; DWORD size; if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buffer, sizeof(buffer), &size, 0, 0) != 0) { ec = error_code(WSAGetLastError(), boost::asio::error::system_category); closesocket(s); return ret; } closesocket(s); int n = size / sizeof(INTERFACE_INFO); ip_interface iface; for (int i = 0; i < n; ++i) { iface.interface_address = sockaddr_to_address(&buffer[i].iiAddress.Address); if (iface.interface_address == address_v4::any()) continue; iface.netmask = sockaddr_to_address(&buffer[i].iiNetmask.Address , iface.interface_address.is_v4() ? AF_INET : AF_INET6); iface.name[0] = 0; iface.mtu = 1500; // how to get the MTU? ret.push_back(iface); } #else #ifdef _MSC_VER #pragma message ( "THIS OS IS NOT RECOGNIZED, enum_net_interfaces WILL PROBABLY NOT WORK" ) #else #warning "THIS OS IS NOT RECOGNIZED, enum_net_interfaces WILL PROBABLY NOT WORK" #endif // make a best guess of the interface we're using and its IP udp::resolver r(ios); udp::resolver::iterator i = r.resolve(udp::resolver::query(boost::asio::ip::host_name(ec), "0"), ec); if (ec) return ret; ip_interface iface; for (;i != udp::resolver_iterator(); ++i) { iface.interface_address = i->endpoint().address(); iface.mtu = 1500; if (iface.interface_address.is_v4()) iface.netmask = address_v4::netmask(iface.interface_address.to_v4()); ret.push_back(iface); } #endif return ret; }
vector<EncodedAttributeInfo*> LoadSavedDataSources::loadCodedAttributesFromMultipleFiles( string dsName,int rowCount,bool limit ) { vector<EncodedAttributeInfo*> codedAtts; try { for (int j = 0 ; j < this->saved_file_names.size() ; j++) { this->_fileName = ConfigurationReader::ReadConfiguration(ConfigurationReader::configutation::SAVE_DATA_FOLDER) + this->_saved_folder + "\\" + this->saved_file_names[j]; TiXmlDocument *doc_1 = new TiXmlDocument(this->_fileName.c_str()); doc_1->LoadFile(); TiXmlHandle handler(doc_1); TiXmlElement *dsElement = handler.FirstChild("DataSources").ToElement(); dsElement = dsElement->FirstChildElement("DataSource"); if (strcmp(dsElement->Attribute("Name"),dsName.c_str()) == 0) { dsElement = dsElement->FirstChildElement("CodedAttribute"); int attID = dsElement->FirstAttribute()->IntValue(); int attType = atoi(dsElement->Attribute("Type")); string attName = dsElement->Attribute("Name"); int noVStreams = dsElement->LastAttribute()->IntValue(); EncodedAttributeInfo* attr; switch(attType){ case 0: { EncodedIntAttribute *intAtt = new EncodedIntAttribute(); intAtt->setAttID(attID); intAtt->setAttName(attName); intAtt->setNoOfVBitStreams(noVStreams,rowCount); intAtt->setAttType(getAttType(attType)); BitStreamInfo** bitStreams = new BitStreamInfo*[noVStreams]; TiXmlElement *vbs = dsElement->FirstChildElement("VBitStreams")->FirstChildElement("vbitstream"); for (int k = 0 ; k < noVStreams ; k++) { BitStreamInfo* bitStr = new VBitStream(); bitStr->setBitCount(rowCount); bitStr->setBitStreamAllocAttID(attID); bitStr->setBitStreamAllocAttName(attName); string bitStream; if (limit) { bitStream = vbs->GetText(); long offset = rowCount - this->_rowLimit; bitStream = bitStream.substr(offset,this->_rowLimit); } else bitStream = vbs->GetText(); dynamic_bitset<> temp(bitStream); bitStr->convert(temp); bitStreams[k] = bitStr; vbs = vbs->NextSiblingElement("vbitstream"); } vector<BitStreamInfo*> tempVB(bitStreams , bitStreams + noVStreams); intAtt->setVBitStreams(tempVB); attr = intAtt; codedAtts.push_back(attr); break; } case 1: { EncodedDoubleAttribute *doubleAtt = new EncodedDoubleAttribute(); doubleAtt->setAttID(attID); doubleAtt->setAttName(attName); doubleAtt->setNoOfVBitStreams(noVStreams,rowCount); doubleAtt->setAttType(getAttType(attType)); BitStreamInfo** bitStreams = new BitStreamInfo*[noVStreams]; TiXmlElement *vbs = dsElement->FirstChildElement("VBitStreams")->FirstChildElement("vbitstream"); for (int k = 0 ; k < noVStreams ; k++) { BitStreamInfo* bitStr = new VBitStream(); bitStr->setBitCount(rowCount); bitStr->setBitStreamAllocAttID(attID); bitStr->setBitStreamAllocAttName(attName); string bitStream; if (limit) { bitStream = vbs->GetText(); long offset = rowCount - this->_rowLimit; bitStream = bitStream.substr(offset,this->_rowLimit); } else bitStream = vbs->GetText(); dynamic_bitset<> temp(bitStream); bitStr->convert(temp); bitStreams[k] = bitStr; vbs = vbs->NextSiblingElement("vbitstream"); } vector<BitStreamInfo*> tempVB(bitStreams , bitStreams + noVStreams); doubleAtt->setVBitStreams(tempVB); attr = doubleAtt; codedAtts.push_back(attr); break; } case 3: { EncodedMultiCatAttribute *catAtt = new EncodedMultiCatAttribute(); catAtt->setAttID(attID); catAtt->setAttName(attName); catAtt->setAttType(getAttType(attType)); catAtt->setNoOfVBitStreams(noVStreams,rowCount); BitStreamInfo** bitStreams = new BitStreamInfo*[noVStreams]; TiXmlElement *vbs = dsElement->FirstChildElement("VBitStreams")->FirstChildElement("vbitstream"); for (int k = 0 ; k < noVStreams ; k++) { BitStreamInfo* bitStr = new VBitStream(); bitStr->setBitCount(rowCount); bitStr->setBitStreamAllocAttID(attID); bitStr->setBitStreamAllocAttName(attName); string bitStream; if (limit) { bitStream = vbs->GetText(); long offset = rowCount - this->_rowLimit; bitStream = bitStream.substr(offset,this->_rowLimit); } else bitStream = vbs->GetText(); dynamic_bitset<> temp(bitStream); bitStr->convert(temp); bitStreams[k] = bitStr; vbs = vbs->NextSiblingElement("vbitstream"); } vector<BitStreamInfo*> tempVB(bitStreams , bitStreams + noVStreams); catAtt->setVBitStreams(tempVB); attr = catAtt; codedAtts.push_back(attr); break; } } } delete doc_1; } } catch(...) { error_loading_encoded_data ex; string err = ExceptionReader::GetError(SM1017); err += "-> Try to load from a multiple attribute data files"; ex << error_message(err); ex << error_code(SM1017); BOOST_THROW_EXCEPTION(ex); } return codedAtts; }