コード例 #1
0
ファイル: tl_jni_object.cpp プロジェクト: najibalghaeth/td
jfieldID get_field_id(JNIEnv *env, jclass clazz, const char *name, const char *signature) {
  jfieldID res = env->GetFieldID(clazz, name, signature);
  if (!res) {
    fatal_error(env, PSLICE() << "Can't find field [" << name << "] with signature [" << signature << "]");
  }
  return res;
}
コード例 #2
0
ファイル: tl_jni_object.cpp プロジェクト: najibalghaeth/td
void init_vars(JNIEnv *env, const char *td_api_java_package) {
  BooleanClass = get_jclass(env, "java/lang/Boolean");
  IntegerClass = get_jclass(env, "java/lang/Integer");
  LongClass = get_jclass(env, "java/lang/Long");
  DoubleClass = get_jclass(env, "java/lang/Double");
  StringClass = get_jclass(env, "java/lang/String");
  ObjectClass = get_jclass(env, (PSLICE() << td_api_java_package << "/TdApi$Object").c_str());
  ArrayKeyboardButtonClass =
      get_jclass(env, (PSLICE() << "[L" << td_api_java_package << "/TdApi$KeyboardButton;").c_str());
  ArrayInlineKeyboardButtonClass =
      get_jclass(env, (PSLICE() << "[L" << td_api_java_package << "/TdApi$InlineKeyboardButton;").c_str());
  GetConstructorID = get_method_id(env, ObjectClass, "getConstructor", "()I");
  BooleanGetValueMethodID = get_method_id(env, BooleanClass, "booleanValue", "()Z");
  IntegerGetValueMethodID = get_method_id(env, IntegerClass, "intValue", "()I");
  LongGetValueMethodID = get_method_id(env, LongClass, "longValue", "()J");
  DoubleGetValueMethodID = get_method_id(env, DoubleClass, "doubleValue", "()D");
}
コード例 #3
0
ファイル: NetQueryDispatcher.cpp プロジェクト: anhdocphys/td
void NetQueryDispatcher::dispatch(NetQueryPtr net_query) {
  net_query->debug("dispatch");
  if (stop_flag_.load(std::memory_order_relaxed)) {
    // Set error to avoid warning
    // No need to send result somewhere, it probably will be ignored anyway
    net_query->set_error(Status::Error(500, "Internal Server Error: closing"));
    net_query->clear();
    net_query.reset();
    // G()->net_query_creator().release(std::move(net_query));
    return;
  }

  if (net_query->is_ready()) {
    if (net_query->is_error()) {
      auto code = net_query->error().code();
      if (code == 303) {
        try_fix_migrate(net_query);
      } else if (code == NetQuery::Resend) {
        net_query->resend();
      } else if (code < 0 || code == 500 || code == 420) {
        net_query->debug("sent to NetQueryDelayer");
        return send_closure(delayer_, &NetQueryDelayer::delay, std::move(net_query));
      }
    }
  }

  if (!net_query->is_ready()) {
    if (net_query->dispatch_ttl == 0) {
      net_query->set_error(Status::Error("DispatchTtlError"));
    }
  }

  auto dest_dc_id = net_query->dc_id();
  if (dest_dc_id.is_main()) {
    dest_dc_id = DcId::internal(main_dc_id_.load(std::memory_order_relaxed));
  }
  if (!net_query->is_ready() && wait_dc_init(dest_dc_id, true).is_error()) {
    net_query->set_error(Status::Error(PSLICE() << "No such dc " << dest_dc_id));
  }

  if (net_query->is_ready()) {
    auto callback = net_query->move_callback();
    if (callback.empty()) {
      net_query->debug("sent to td (no callback)");
      send_closure(G()->td(), &NetQueryCallback::on_result, std::move(net_query));
    } else {
      net_query->debug("sent to callback", true);
      send_closure(std::move(callback), &NetQueryCallback::on_result, std::move(net_query));
    }
    return;
  }

  if (net_query->dispatch_ttl > 0) {
    net_query->dispatch_ttl--;
  }

  size_t dc_pos = static_cast<size_t>(dest_dc_id.get_raw_id() - 1);
  CHECK(dc_pos < dcs_.size());
  switch (net_query->type()) {
    case NetQuery::Type::Common:
      net_query->debug(PSTRING() << "sent to main session multi proxy " << dest_dc_id);
      send_closure_later(dcs_[dc_pos].main_session_, &SessionMultiProxy::send, std::move(net_query));
      break;
    case NetQuery::Type::Upload:
      net_query->debug(PSTRING() << "sent to upload session multi proxy " << dest_dc_id);
      send_closure_later(dcs_[dc_pos].upload_session_, &SessionMultiProxy::send, std::move(net_query));
      break;
    case NetQuery::Type::Download:
      net_query->debug(PSTRING() << "sent to download session multi proxy " << dest_dc_id);
      send_closure_later(dcs_[dc_pos].download_session_, &SessionMultiProxy::send, std::move(net_query));
      break;
    case NetQuery::Type::DownloadSmall:
      net_query->debug(PSTRING() << "sent to download small session multi proxy " << dest_dc_id);
      send_closure_later(dcs_[dc_pos].download_small_session_, &SessionMultiProxy::send, std::move(net_query));
      break;
  }
}
コード例 #4
0
ファイル: NetQueryDispatcher.cpp プロジェクト: anhdocphys/td
Status NetQueryDispatcher::wait_dc_init(DcId dc_id, bool force) {
  // TODO: optimize
  if (!dc_id.is_exact()) {
    return Status::Error("Not exact DC");
  }
  size_t pos = static_cast<size_t>(dc_id.get_raw_id() - 1);
  if (pos >= dcs_.size()) {
    return Status::Error("Too big DC id");
  }
  auto &dc = dcs_[pos];

  bool should_init = false;
  if (!dc.is_valid_) {
    if (!force) {
      return Status::Error("Invalid DC");
    }
    bool expected = false;
    should_init =
        dc.is_valid_.compare_exchange_strong(expected, true, std::memory_order_seq_cst, std::memory_order_seq_cst);
  }

  if (should_init) {
    std::lock_guard<std::mutex> guard(main_dc_id_mutex_);
    if (stop_flag_.load(std::memory_order_relaxed)) {
      return Status::Error("Closing");
    }
    // init dc
    decltype(common_public_rsa_key_) public_rsa_key;
    bool is_cdn = false;
    if (dc_id.is_internal()) {
      public_rsa_key = common_public_rsa_key_;
    } else {
      public_rsa_key = std::make_shared<PublicRsaKeyShared>(dc_id);
      send_closure_later(public_rsa_key_watchdog_, &PublicRsaKeyWatchdog::add_public_rsa_key, public_rsa_key);
      is_cdn = true;
    }
    auto auth_data = AuthDataShared::create(dc_id, std::move(public_rsa_key), td_guard_);
    int32 session_count = get_session_count();
    bool use_pfs = get_use_pfs();

    int32 slow_net_scheduler_id = G()->get_slow_net_scheduler_id();

    auto raw_dc_id = dc_id.get_raw_id();
    dc.main_session_ = create_actor<SessionMultiProxy>(PSLICE() << "SessionMultiProxy:" << raw_dc_id << ":main",
                                                       session_count, auth_data, raw_dc_id == main_dc_id_,
                                                       use_pfs || (session_count > 1), false, false, is_cdn);
    dc.upload_session_ = create_actor_on_scheduler<SessionMultiProxy>(
        PSLICE() << "SessionMultiProxy:" << raw_dc_id << ":upload", slow_net_scheduler_id,
        raw_dc_id != 2 && raw_dc_id != 4 ? 8 : 4, auth_data, false, use_pfs || (session_count > 1), false, true,
        is_cdn);
    dc.download_session_ = create_actor_on_scheduler<SessionMultiProxy>(
        PSLICE() << "SessionMultiProxy:" << raw_dc_id << ":download", slow_net_scheduler_id, 1, auth_data, false,
        use_pfs, true, true, is_cdn);
    dc.download_small_session_ = create_actor_on_scheduler<SessionMultiProxy>(
        PSLICE() << "SessionMultiProxy:" << raw_dc_id << ":download_small", slow_net_scheduler_id, 1, auth_data, false,
        use_pfs, true, true, is_cdn);
    dc.is_inited_ = true;
    if (dc_id.is_internal()) {
      send_closure_later(dc_auth_manager_, &DcAuthManager::add_dc, std::move(auth_data));
    }
  } else {
    while (!dc.is_inited_) {
      if (stop_flag_.load(std::memory_order_relaxed)) {
        return Status::Error("Closing");
      }
#if !TD_THREAD_UNSUPPORTED
      td::this_thread::yield();
#endif
    }
  }
  return Status::OK();
}
コード例 #5
0
ファイル: ConfigShared.cpp プロジェクト: najibalghaeth/td
void ConfigShared::set_option_string(Slice name, Slice value) {
  if (set_option(name, PSLICE() << "S" << value)) {
    on_option_updated(name);
  }
}
コード例 #6
0
ファイル: ConfigShared.cpp プロジェクト: najibalghaeth/td
void ConfigShared::set_option_integer(Slice name, int32 value) {
  if (set_option(name, PSLICE() << "I" << value)) {
    on_option_updated(name);
  }
}
コード例 #7
0
ファイル: tl_jni_object.cpp プロジェクト: najibalghaeth/td
void register_native_method(JNIEnv *env, jclass clazz, std::string name, std::string signature, void *function_ptr) {
  JNINativeMethod native_method{&name[0], &signature[0], function_ptr};
  if (env->RegisterNatives(clazz, &native_method, 1) != 0) {
    fatal_error(env, PSLICE() << "RegisterNatives failed for " << name << " with signature " << signature);
  }
}
コード例 #8
0
ファイル: SslFd.cpp プロジェクト: najibalghaeth/td
Result<SslFd> SslFd::init(SocketFd fd, CSlice host, CSlice cert_file, VerifyPeer verify_peer) {
#if TD_WINDOWS
  return Status::Error("TODO");
#else
  static bool init_openssl = [] {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
    return OPENSSL_init_ssl(0, nullptr) != 0;
#else
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    return OpenSSL_add_ssl_algorithms() != 0;
#endif
  }();
  CHECK(init_openssl);

  openssl_clear_errors("Before SslFd::init");
  CHECK(!fd.empty());

  auto ssl_method =
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
      TLS_client_method();
#else
      SSLv23_client_method();
#endif
  if (ssl_method == nullptr) {
    return create_openssl_error(-6, "Failed to create an SSL client method");
  }

  auto ssl_ctx = SSL_CTX_new(ssl_method);
  if (ssl_ctx == nullptr) {
    return create_openssl_error(-7, "Failed to create an SSL context");
  }
  auto ssl_ctx_guard = ScopeExit() + [&]() { SSL_CTX_free(ssl_ctx); };
  long options = 0;
#ifdef SSL_OP_NO_SSLv2
  options |= SSL_OP_NO_SSLv2;
#endif
#ifdef SSL_OP_NO_SSLv3
  options |= SSL_OP_NO_SSLv3;
#endif
  SSL_CTX_set_options(ssl_ctx, options);
  SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);

  if (cert_file.empty()) {
    SSL_CTX_set_default_verify_paths(ssl_ctx);
  } else {
    if (SSL_CTX_load_verify_locations(ssl_ctx, cert_file.c_str(), nullptr) == 0) {
      return create_openssl_error(-8, "Failed to set custom cert file");
    }
  }
  if (VERIFY_PEER && verify_peer == VerifyPeer::On) {
    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, verify_callback);

    if (VERIFY_DEPTH != -1) {
      SSL_CTX_set_verify_depth(ssl_ctx, VERIFY_DEPTH);
    }
  } else {
    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, nullptr);
  }

  // TODO(now): cipher list
  string cipher_list;
  if (SSL_CTX_set_cipher_list(ssl_ctx, cipher_list.empty() ? "DEFAULT" : cipher_list.c_str()) == 0) {
    return create_openssl_error(-9, PSLICE("Failed to set cipher list \"%s\"", cipher_list.c_str()));
  }

  auto ssl_handle = SSL_new(ssl_ctx);
  if (ssl_handle == nullptr) {
    return create_openssl_error(-13, "Failed to create an SSL handle");
  }
  auto ssl_handle_guard = ScopeExit() + [&]() {
    do_ssl_shutdown(ssl_handle);
    SSL_free(ssl_handle);
  };

#if OPENSSL_VERSION_NUMBER >= 0x10002000L
  X509_VERIFY_PARAM *param = SSL_get0_param(ssl_handle);
  /* Enable automatic hostname checks */
  // TODO: X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
  X509_VERIFY_PARAM_set_hostflags(param, 0);
  X509_VERIFY_PARAM_set1_host(param, host.c_str(), 0);
#else
#warning DANGEROUS! HTTPS HOST WILL NOT BE CHECKED. INSTALL OPENSSL >= 1.0.2 OR IMPLEMENT HTTPS HOST CHECK MANUALLY
#endif

  if (!SSL_set_fd(ssl_handle, fd.get_fd().get_native_fd())) {
    return create_openssl_error(-14, "Failed to set fd");
  }

#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
  auto host_str = host.str();
  SSL_set_tlsext_host_name(ssl_handle, MutableCSlice(host_str).begin());
#endif
  SSL_set_connect_state(ssl_handle);

  ssl_ctx_guard.dismiss();
  ssl_handle_guard.dismiss();
  return SslFd(std::move(fd), ssl_handle, ssl_ctx);
#endif
}