std::string engine::filelink(std::string server,
            const std::string& key,
            const std::string& expire,
            const std::string& file,
            report_level s,
            validate_cert v)
{
    init_curl(key, s, v);
    std::string a = attach_impl(server, file, s);
    return filelink_impl(server, expire, a, s);
}
void engine::attach(std::string server,
        const std::string& key,
        const strings& fs,
        report_level s,
        validate_cert v)
{
    init_curl(key, s, v);
    strings::const_iterator i = fs.begin();
    for (; i != fs.end(); ++i) {
        attach_impl(server, *i, s);
    }
}
void local_actor::join(const group& what) {
  CAF_LOG_TRACE(CAF_TSARG(what));
  if (what == invalid_group) {
    return;
  }
  abstract_group::subscription_token tk{what.ptr()};
  std::unique_lock<std::mutex> guard{m_mtx};
  if (detach_impl(tk, m_attachables_head, true, true) == 0) {
    auto ptr = what->subscribe(address());
    if (ptr) {
      attach_impl(ptr);
    }
  }
}
void monitorable_actor::attach(attachable_ptr ptr) {
  CAF_LOG_TRACE("");
  CAF_ASSERT(ptr != nullptr);
  error fail_state;
  auto attached = exclusive_critical_section([&] {
    if (getf(is_terminated_flag)) {
      fail_state = fail_state_;
      return false;
    }
    attach_impl(ptr);
    return true;
  });
  CAF_LOG_DEBUG("cannot attach functor to terminated actor: call immediately");
  if (!attached)
    ptr->actor_exited(fail_state, nullptr);
}
void abstract_actor::attach(attachable_ptr ptr) {
  CAF_LOG_TRACE("");
  if (ptr == nullptr) {
    return;
  }
  uint32_t reason;
  { // lifetime scope of guard
    guard_type guard{mtx_};
    reason = exit_reason_;
    if (reason == exit_reason::not_exited) {
      attach_impl(ptr);
      return;
    }
  }
  CAF_LOG_DEBUG("cannot attach functor to terminated actor: call immediately");
  ptr->actor_exited(this, reason);
}
bool abstract_actor::establish_link_impl(const actor_addr& other) {
  CAF_LOG_TRACE(CAF_TSARG(other));
  if (other && other != this) {
    guard_type guard{mtx_};
    auto ptr = actor_cast<abstract_actor_ptr>(other);
    // send exit message if already exited
    if (exited()) {
      ptr->enqueue(address(), invalid_message_id,
                   make_message(exit_msg{address(), exit_reason()}), host_);
    } else if (ptr->establish_backlink(address())) {
      // add link if not already linked to other
      // (checked by establish_backlink)
      auto tmp = default_attachable::make_link(other);
      attach_impl(tmp);
      return true;
    }
  }
  return false;
}
std::string engine::send(std::string server,
        const std::string& key,
        const std::string& user,
        const std::string& subject,
        const std::string& message,
        const strings& fs,
        report_level s,
        validate_cert v)
{
    init_curl(key, s, v);
    std::set<std::string> attachments;
    strings::const_iterator i = fs.begin();
    for (; i != fs.end(); ++i) {
        std::string a = attach_impl(server, *i, s);
        attachments.insert(a);
    }
    return send_attachments_impl(server, user, subject, message,
            attachments, s);
}
void monitorable_actor::add_link(abstract_actor* x) {
  // Add backlink on `x` first and add the local attachable only on success.
  CAF_LOG_TRACE(CAF_ARG(x));
  CAF_ASSERT(x != nullptr);
  error fail_state;
  bool send_exit_immediately = false;
  auto tmp = default_attachable::make_link(address(), x->address());
  joined_exclusive_critical_section(this, x, [&] {
    if (getf(is_terminated_flag)) {
      fail_state = fail_state_;
      send_exit_immediately = true;
    } else if (x->add_backlink(this)) {
      attach_impl(tmp);
    }
  });
  if (send_exit_immediately)
    x->enqueue(nullptr, invalid_message_id,
                 make_message(exit_msg{address(), fail_state}), nullptr);
}
void engine::filedrop(std::string server,
        const std::string& user,
        const std::string& subject,
        const std::string& message,
        const strings& fs,
        report_level s,
        validate_cert v)
{
    std::string key = get_filedrop_api_key(server, s, v);
    init_curl(key, s, v);
    strings::const_iterator i = fs.begin();
    strings rs;
    std::string url = get_server_from_filedrop(server);
    for (; i != fs.end(); ++i) {
        std::string id = attach_impl(url, *i, s);
        rs.insert(id);
    }
    curl_easy_setopt(m_curl, CURLOPT_USERPWD, "");
    filedrop_attachments_impl(server, key, user, subject, message,
            rs, s);
}
bool monitorable_actor::add_backlink(abstract_actor* x) {
  // Called in an exclusive critical section.
  CAF_LOG_TRACE(CAF_ARG(x));
  CAF_ASSERT(x);
  error fail_state;
  bool send_exit_immediately = false;
  default_attachable::observe_token tk{x->address(),
                                       default_attachable::link};
  auto tmp = default_attachable::make_link(address(), x->address());
  auto success = false;
  if (getf(is_terminated_flag)) {
    fail_state = fail_state_;
    send_exit_immediately = true;
  } else if (detach_impl(tk, true, true) == 0) {
    attach_impl(tmp);
    success = true;
  }
  if (send_exit_immediately)
    x->enqueue(nullptr, invalid_message_id,
               make_message(exit_msg{address(), fail_state}), nullptr);
  return success;
}
bool abstract_actor::establish_backlink_impl(const actor_addr& other) {
  CAF_LOG_TRACE(CAF_TSARG(other));
  uint32_t reason = exit_reason::not_exited;
  default_attachable::observe_token tk{other, default_attachable::link};
  if (other && other != this) {
    guard_type guard{mtx_};
    reason = exit_reason_;
    if (reason == exit_reason::not_exited) {
      if (detach_impl(tk, attachables_head_, true, true) == 0) {
        auto tmp = default_attachable::make_link(other);
        attach_impl(tmp);
        return true;
      }
    }
  }
  // send exit message without lock
  if (reason != exit_reason::not_exited) {
    auto ptr = actor_cast<abstract_actor_ptr>(other);
    ptr->enqueue(address(), invalid_message_id,
                 make_message(exit_msg{address(), exit_reason()}), host_);
  }
  return false;
}