I’m trying to use Gun to communicate with the Discord API for educational purposes (I chose Gun for being a lower-level tool to understand some complexities), and I’m having issues during the handshake with the Discord WebSocket gateway. I’m receiving the following error:
(MatchError) no match of right hand side value: {:error, {:down, {:shutdown, {:tls_alert, {:internal_error, ~c"TLS client: In state wait_cert_cr at ssl_handshake .erl:364 generated CLIENT ALERT: Fatal - Internal Error\n {unexpected_error,undef}"}}}}}
Please note that my :gun.ws_upgrade
is failing during the handshake when transitioning from HTTP to WebSocket. I have no idea what might be wrong to reach this point with this error. Can you shed some light on what could be the issue and how to fix it?
Here is my code
def test do
opts2 = %{
connect_timeout: 60000,
retry: 10,
retry_timeout: 300,
transport: :tls,
tls_opts: [
verify: :verify_none,
cacerts: :certifi.cacerts(),
depth: 99,
reuse_sessions: false
],
http_opts: %{version: :"HTTP/1.1"},
protocols: [:http],
}
opts = %{
connect_timeout: 60000,
retry: 10,
retry_timeout: 300,
transport: :tls,
tls_opts: [
verify: :verify_peer,
cacertfile: CAStore.file_path(),
depth: 99,
reuse_sessions: false,
verify_fun: {&:ssl_verify_hostname.verify_fun/3, [check_hostname: 'gateway.discord.gg']}
],
http_opts: %{version: :"HTTP/1.1"},
protocols: [:http],
}
{:ok, conn} = :gun.open('discord.com', 443, opts2)
{:ok, _} = :gun.await_up(conn)
stream = :gun.get(conn, "/api/v10/gateway")
{response, :nofin, 200, headers} = :gun.await(conn, stream)
{:ok, body} = :gun.await_body(conn, stream)
{:ok, map} = Jason.decode(body)
IO.inspect(map["url"])
{:ok, conn} = :gun.open('gateway.discord.gg', 443, opts)
{:ok, _} = :gun.await_up(conn)
:timer.sleep(1000)
stream = :gun.ws_upgrade(conn, '/?v=10&encoding=json', headers, opts)
receive do
{:gun_upgrade, _, _} ->
IO.puts("WebSocket Upgrade Successful")
connected(conn)
{:gun_error, _reason} ->
IO.puts("WebSocket Upgrade Error")
after
5000 ->
IO.puts("WebSocket Upgrade Timeout")
end
end
defp connected(conn) do
receive do
something ->
IO.puts("Received WebSocket Text Frame")
connected(conn)
{:gun_close, _status, _reason} ->
IO.puts("WebSocket Connection Closed")
after
5000 ->
IO.puts("WebSocket Communication Timeout")
end
end