예제 #1
0
std::vector<std::string> DNSResolver::get_record(const std::string& url, int record_type, boost::optional<std::string> (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid)
{
  std::vector<std::string> addresses;
  dnssec_available = false;
  dnssec_valid = false;

  if (!check_address_syntax(url.c_str()))
  {
    return addresses;
  }

  // destructor takes care of cleanup
  ub_result_ptr result;

  // call DNS resolver, blocking.  if return value not zero, something went wrong
  if (!ub_resolve(m_data->m_ub_context, string_copy(url.c_str()), record_type, DNS_CLASS_IN, &result))
  {
    dnssec_available = (result->secure || result->bogus);
    dnssec_valid = result->secure && !result->bogus;
    if (result->havedata)
    {
      for (size_t i=0; result->data[i] != NULL; i++)
      {
        boost::optional<std::string> res = (*reader)(result->data[i], result->len[i]);
        if (res)
        {
          MINFO("Found \"" << *res << "\" in " << get_record_name(record_type) << " record for " << url);
          addresses.push_back(*res);
        }
      }
    }
  }

  return addresses;
}
예제 #2
0
 virtual bool on_header(const epee::net_utils::http::http_response_info &headers)
 {
   ssize_t length;
   if (epee::string_tools::get_xtype_from_string(length, headers.m_header_info.m_content_length) && length >= 0)
   {
     MINFO("Content-Length: " << length);
     content_length = length;
     boost::filesystem::path path(control->path);
     boost::filesystem::space_info si = boost::filesystem::space(path);
     if (si.available < (size_t)content_length)
     {
       const uint64_t avail = (si.available + 1023) / 1024, needed = (content_length + 1023) / 1024;
       MERROR("Not enough space to download " << needed << " kB to " << path << " (" << avail << " kB available)");
       return false;
     }
   }
   return true;
 }
예제 #3
0
DNSResolver::DNSResolver() : m_data(new DNSResolverData())
{
  int use_dns_public = 0;
  std::vector<std::string> dns_public_addr;
  if (auto res = getenv("DNS_PUBLIC"))
  {
    dns_public_addr = tools::dns_utils::parse_dns_public(res);
    if (!dns_public_addr.empty())
    {
      MGINFO("Using public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)");
      use_dns_public = 1;
    }
    else
    {
      MERROR("Failed to parse DNS_PUBLIC");
    }
  }

  // init libunbound context
  m_data->m_ub_context = ub_ctx_create();

  if (use_dns_public)
  {
    for (const auto &ip: dns_public_addr)
      ub_ctx_set_fwd(m_data->m_ub_context, string_copy(ip.c_str()));
    ub_ctx_set_option(m_data->m_ub_context, string_copy("do-udp:"), string_copy("no"));
    ub_ctx_set_option(m_data->m_ub_context, string_copy("do-tcp:"), string_copy("yes"));
  }
  else {
    // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent
    ub_ctx_resolvconf(m_data->m_ub_context, NULL);
    ub_ctx_hosts(m_data->m_ub_context, NULL);
  }

  const char * const *ds = ::get_builtin_ds();
  while (*ds)
  {
    MINFO("adding trust anchor: " << *ds);
    ub_ctx_add_ta(m_data->m_ub_context, string_copy(*ds++));
  }
}
예제 #4
0
  static void download_thread(download_async_handle control)
  {
    static std::atomic<unsigned int> thread_id(0);

    MLOG_SET_THREAD_NAME("DL" + std::to_string(thread_id++));

    struct stopped_setter
    {
      stopped_setter(const download_async_handle &control): control(control) {}
      ~stopped_setter() { control->stopped = true; }
      download_async_handle control;
    } stopped_setter(control);

    try
    {
      boost::unique_lock<boost::mutex> lock(control->mutex);
      MINFO("Downloading " << control->uri << " to " << control->path);
      std::ofstream f;
      f.open(control->path, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
      if (!f.good()) {
        MERROR("Failed to open file " << control->path);
        control->result_cb(control->path, control->uri, control->success);
        return;
      }
      class download_client: public epee::net_utils::http::http_simple_client
      {
      public:
        download_client(download_async_handle control, std::ofstream &f):
          control(control), f(f), content_length(-1), total(0) {}
        virtual ~download_client() { f.close(); }
        virtual bool on_header(const epee::net_utils::http::http_response_info &headers)
        {
          ssize_t length;
          if (epee::string_tools::get_xtype_from_string(length, headers.m_header_info.m_content_length) && length >= 0)
          {
            MINFO("Content-Length: " << length);
            content_length = length;
            boost::filesystem::path path(control->path);
            boost::filesystem::space_info si = boost::filesystem::space(path);
            if (si.available < (size_t)content_length)
            {
              const uint64_t avail = (si.available + 1023) / 1024, needed = (content_length + 1023) / 1024;
              MERROR("Not enough space to download " << needed << " kB to " << path << " (" << avail << " kB available)");
              return false;
            }
          }
          return true;
        }
        virtual bool handle_target_data(std::string &piece_of_transfer)
        {
          try
          {
            boost::lock_guard<boost::mutex> lock(control->mutex);
            if (control->stop)
              return false;
            f << piece_of_transfer;
            total += piece_of_transfer.size();
            if (control->progress_cb && !control->progress_cb(control->path, control->uri, total, content_length))
              return false;
            return f.good();
          }
          catch (const std::exception &e)
          {
            MERROR("Error writing data: " << e.what());
            return false;
          }
        }
      private:
        download_async_handle control;
        std::ofstream &f;
        ssize_t content_length;
        size_t total;
      } client(control, f);
      epee::net_utils::http::url_content u_c;
      if (!epee::net_utils::parse_url(control->uri, u_c))
      {
        MERROR("Failed to parse URL " << control->uri);
        control->result_cb(control->path, control->uri, control->success);
        return;
      }
      if (u_c.host.empty())
      {
        MERROR("Failed to determine address from URL " << control->uri);
        control->result_cb(control->path, control->uri, control->success);
        return;
      }

      lock.unlock();

      uint16_t port = u_c.port ? u_c.port : 80;
      MDEBUG("Connecting to " << u_c.host << ":" << port);
      client.set_server(u_c.host, std::to_string(port), boost::none);
      if (!client.connect(std::chrono::seconds(30)))
      {
        boost::lock_guard<boost::mutex> lock(control->mutex);
        MERROR("Failed to connect to " << control->uri);
        control->result_cb(control->path, control->uri, control->success);
        return;
      }
      MDEBUG("GETting " << u_c.uri);
      const epee::net_utils::http::http_response_info *info = NULL;
      if (!client.invoke_get(u_c.uri, std::chrono::seconds(30), "", &info))
      {
        boost::lock_guard<boost::mutex> lock(control->mutex);
        MERROR("Failed to connect to " << control->uri);
        client.disconnect();
        control->result_cb(control->path, control->uri, control->success);
        return;
      }
      if (control->stop)
      {
        boost::lock_guard<boost::mutex> lock(control->mutex);
        MDEBUG("Download cancelled");
        client.disconnect();
        control->result_cb(control->path, control->uri, control->success);
        return;
      }
      if (!info)
      {
        boost::lock_guard<boost::mutex> lock(control->mutex);
        MERROR("Failed invoking GET command to " << control->uri << ", no status info returned");
        client.disconnect();
        control->result_cb(control->path, control->uri, control->success);
        return;
      }
      MDEBUG("response code: " << info->m_response_code);
      MDEBUG("response length: " << info->m_header_info.m_content_length);
      MDEBUG("response comment: " << info->m_response_comment);
      MDEBUG("response body: " << info->m_body);
      for (const auto &f: info->m_additional_fields)
        MDEBUG("additional field: " << f.first << ": " << f.second);
      if (info->m_response_code != 200)
      {
        boost::lock_guard<boost::mutex> lock(control->mutex);
        MERROR("Status code " << info->m_response_code);
        client.disconnect();
        control->result_cb(control->path, control->uri, control->success);
        return;
      }
      client.disconnect();
      f.close();
      MDEBUG("Download complete");
      lock.lock();
      control->success = true;
      control->result_cb(control->path, control->uri, control->success);
      return;
    }
    catch (const std::exception &e)
    {
      MERROR("Exception in download thread: " << e.what());
      // fall through and call result_cb not from the catch block to avoid another exception
    }
    boost::lock_guard<boost::mutex> lock(control->mutex);
    control->result_cb(control->path, control->uri, control->success);
  }
예제 #5
0
파일: wallet_args.cpp 프로젝트: aeonix/aeon
  std::pair<boost::optional<boost::program_options::variables_map>, bool> main(
    int argc, char** argv,
    const char* const usage,
    const char* const notice,
    boost::program_options::options_description desc_params,
    const boost::program_options::positional_options_description& positional_options,
    const std::function<void(const std::string&, bool)> &print,
    const char *default_log_name,
    bool log_to_console)
  
  {
    namespace bf = boost::filesystem;
    namespace po = boost::program_options;
#ifdef WIN32
    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""};
    const command_line::arg_descriptor<std::size_t> arg_max_log_file_size = {"max-log-file-size", "Specify maximum log file size [B]", MAX_LOG_FILE_SIZE};
    const command_line::arg_descriptor<std::size_t> arg_max_log_files = {"max-log-files", "Specify maximum number of rotated log files to be saved (no limit by setting to 0)", MAX_LOG_FILES};
    const command_line::arg_descriptor<uint32_t> arg_max_concurrency = {"max-concurrency", wallet_args::tr("Max number of threads to use for a parallel job"), DEFAULT_MAX_CONCURRENCY};
    const command_line::arg_descriptor<std::string> arg_log_file = {"log-file", wallet_args::tr("Specify log file"), ""};
    const command_line::arg_descriptor<std::string> arg_config_file = {"config-file", wallet_args::tr("Config file"), "", true};


    std::string lang = i18n_get_language();
    tools::on_startup();
    tools::set_strict_default_file_permissions(true);

    epee::string_tools::set_module_name_and_folder(argv[0]);

    po::options_description desc_general(wallet_args::tr("General options"));
    command_line::add_arg(desc_general, command_line::arg_help);
    command_line::add_arg(desc_general, command_line::arg_version);

    command_line::add_arg(desc_params, arg_log_file);
    command_line::add_arg(desc_params, arg_log_level);
    command_line::add_arg(desc_params, arg_max_log_file_size);
    command_line::add_arg(desc_params, arg_max_log_files);
    command_line::add_arg(desc_params, arg_max_concurrency);
    command_line::add_arg(desc_params, arg_config_file);

    i18n_set_language("translations", "monero", lang);

    po::options_description desc_all;
    desc_all.add(desc_general).add(desc_params);
    po::variables_map vm;
    bool should_terminate = false;
    bool r = command_line::handle_error_helper(desc_all, [&]()
    {
      auto parser = po::command_line_parser(argc, argv).options(desc_all).positional(positional_options);
      po::store(parser.run(), vm);

      if (command_line::get_arg(vm, command_line::arg_help))
      {
        Print(print) << "Aeon '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
        Print(print) << wallet_args::tr("This is the command line Aeon wallet. It needs to connect to a Aeon\n"
												  "daemon to work correctly.") << ENDL;
        Print(print) << wallet_args::tr("Usage:") << ENDL << "  " << usage;
        Print(print) << desc_all;
        should_terminate = true;
        return true;
      }
      else if (command_line::get_arg(vm, command_line::arg_version))
      {
        Print(print) << "Aeon '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
        should_terminate = true;
        return true;
      }

      if(command_line::has_arg(vm, arg_config_file))
      {
        std::string config = command_line::get_arg(vm, arg_config_file);
        bf::path config_path(config);
        boost::system::error_code ec;
        if (bf::exists(config_path, ec))
        {
          po::store(po::parse_config_file<char>(config_path.string<std::string>().c_str(), desc_params), vm);
        }
        else
        {
          MERROR(wallet_args::tr("Can't find config file ") << config);
          return false;
        }
      }

      po::notify(vm);
      return true;
    });
    if (!r)
      return {boost::none, true};

    if (should_terminate)
      return {std::move(vm), should_terminate};

    std::string log_path;
    if (!command_line::is_arg_defaulted(vm, arg_log_file))
      log_path = command_line::get_arg(vm, arg_log_file);
    else
      log_path = mlog_get_default_log_path(default_log_name);
    mlog_configure(log_path, log_to_console, command_line::get_arg(vm, arg_max_log_file_size), command_line::get_arg(vm, arg_max_log_files));
    if (!command_line::is_arg_defaulted(vm, arg_log_level))
    {
      mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
    }
    else if (!log_to_console)
    {
      mlog_set_categories("");
    }

    if (notice)
      Print(print) << notice << ENDL;

    if (!command_line::is_arg_defaulted(vm, arg_max_concurrency))
      tools::set_max_concurrency(command_line::get_arg(vm, arg_max_concurrency));

    Print(print) << "Aeon '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";

    if (!command_line::is_arg_defaulted(vm, arg_log_level))
      MINFO("Setting log level = " << command_line::get_arg(vm, arg_log_level));
    else
      MINFO("Setting log levels = " << getenv("AEON_LOGS"));
    MINFO(wallet_args::tr("Logging to: ") << log_path);

    Print(print) << boost::format(wallet_args::tr("Logging to %s")) % log_path;

    return {std::move(vm), should_terminate};
  }
void network_throttle::set_target_speed( network_speed_kbps target ) 
{
    m_target_speed = target * 1024;
	MINFO("Setting LIMIT: " << target << " kbps");
	set_real_target_speed(target);
}