X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fgun%2Fconn.ex;h=75b1ffc0a6a1cef762cc44de0815047eb5efb0d3;hb=a781ac6ca5b7ab23eea795331db0a3fff406630e;hp=2474829d6561b9f5fb3af6d0602a1c45e46094dc;hpb=13918cb545d583decfb728300850b307c59e2031;p=akkoma
diff --git a/lib/pleroma/gun/conn.ex b/lib/pleroma/gun/conn.ex
index 2474829d6..75b1ffc0a 100644
--- a/lib/pleroma/gun/conn.ex
+++ b/lib/pleroma/gun/conn.ex
@@ -1,29 +1,135 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Gun.Conn do
- @moduledoc """
- Struct for gun connection data
- """
- @type gun_state :: :up | :down
- @type conn_state :: :active | :idle
-
- @type t :: %__MODULE__{
- conn: pid(),
- gun_state: gun_state(),
- conn_state: conn_state(),
- used_by: [pid()],
- last_reference: pos_integer(),
- crf: float(),
- retries: pos_integer()
- }
-
- defstruct conn: nil,
- gun_state: :open,
- conn_state: :init,
- used_by: [],
- last_reference: 0,
- crf: 1,
- retries: 0
+ alias Pleroma.Gun
+
+ require Logger
+
+ def open(%URI{} = uri, opts) do
+ pool_opts = Pleroma.Config.get([:connections_pool], [])
+
+ opts =
+ opts
+ |> Enum.into(%{})
+ |> Map.put_new(:connect_timeout, pool_opts[:connect_timeout] || 5_000)
+ |> Map.put_new(:supervise, false)
+ |> maybe_add_tls_opts(uri)
+
+ do_open(uri, opts)
+ end
+
+ defp maybe_add_tls_opts(opts, %URI{scheme: "http"}), do: opts
+
+ defp maybe_add_tls_opts(opts, %URI{scheme: "https"}) do
+ tls_opts = [
+ verify: :verify_peer,
+ cacertfile: CAStore.file_path(),
+ depth: 20,
+ reuse_sessions: false,
+ log_level: :warning,
+ customize_hostname_check: [match_fun: :public_key.pkix_verify_hostname_match_fun(:https)]
+ ]
+
+ tls_opts =
+ if Keyword.keyword?(opts[:tls_opts]) do
+ Keyword.merge(tls_opts, opts[:tls_opts])
+ else
+ tls_opts
+ end
+
+ Map.put(opts, :tls_opts, tls_opts)
+ end
+
+ defp do_open(uri, %{proxy: {proxy_host, proxy_port}} = opts) do
+ connect_opts =
+ uri
+ |> destination_opts()
+ |> add_http2_opts(uri.scheme, Map.get(opts, :tls_opts, []))
+
+ with open_opts <- Map.delete(opts, :tls_opts),
+ {:ok, conn} <- Gun.open(proxy_host, proxy_port, open_opts),
+ {:ok, _} <- Gun.await_up(conn, opts[:connect_timeout]),
+ stream <- Gun.connect(conn, connect_opts),
+ {:response, :fin, 200, _} <- Gun.await(conn, stream) do
+ {:ok, conn}
+ else
+ error ->
+ Logger.warn(
+ "Opening proxied connection to #{compose_uri_log(uri)} failed with error #{
+ inspect(error)
+ }"
+ )
+
+ error
+ end
+ end
+
+ defp do_open(uri, %{proxy: {proxy_type, proxy_host, proxy_port}} = opts) do
+ version =
+ proxy_type
+ |> to_string()
+ |> String.last()
+ |> case do
+ "4" -> 4
+ _ -> 5
+ end
+
+ socks_opts =
+ uri
+ |> destination_opts()
+ |> add_http2_opts(uri.scheme, Map.get(opts, :tls_opts, []))
+ |> Map.put(:version, version)
+
+ opts =
+ opts
+ |> Map.put(:protocols, [:socks])
+ |> Map.put(:socks_opts, socks_opts)
+
+ with {:ok, conn} <- Gun.open(proxy_host, proxy_port, opts),
+ {:ok, _} <- Gun.await_up(conn, opts[:connect_timeout]) do
+ {:ok, conn}
+ else
+ error ->
+ Logger.warn(
+ "Opening socks proxied connection to #{compose_uri_log(uri)} failed with error #{
+ inspect(error)
+ }"
+ )
+
+ error
+ end
+ end
+
+ defp do_open(%URI{host: host, port: port} = uri, opts) do
+ host = Pleroma.HTTP.AdapterHelper.parse_host(host)
+
+ with {:ok, conn} <- Gun.open(host, port, opts),
+ {:ok, _} <- Gun.await_up(conn, opts[:connect_timeout]) do
+ {:ok, conn}
+ else
+ error ->
+ Logger.warn(
+ "Opening connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
+ )
+
+ error
+ end
+ end
+
+ defp destination_opts(%URI{host: host, port: port}) do
+ host = Pleroma.HTTP.AdapterHelper.parse_host(host)
+ %{host: host, port: port}
+ end
+
+ defp add_http2_opts(opts, "https", tls_opts) do
+ Map.merge(opts, %{protocols: [:http2], transport: :tls, tls_opts: tls_opts})
+ end
+
+ defp add_http2_opts(opts, _, _), do: opts
+
+ def compose_uri_log(%URI{scheme: scheme, host: host, path: path}) do
+ "#{scheme}://#{host}#{path}"
+ end
end