DTLS error {:key_exists, ...}

I’m trying to get parts of webrtc stack to work with elixir, but right now I’m stuck with this DTLS error.

[error] Acceptor process (pid #PID<0.257.0>) unexpectedly crashed:
** (stop) {:key_exists, {{192, 168, 1, 48}, 53780}}
    (stdlib) gb_trees.erl:319: :gb_trees.insert_1/4
    (stdlib) gb_trees.erl:278: :gb_trees.insert/3
    (ssl) dtls_udp_listener.erl:238: :dtls_udp_listener.setup_new_connection/5
    (ssl) dtls_udp_listener.erl:138: :dtls_udp_listener.handle_info/2
    (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:686: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

Why does it try to setup a connection multiple times? I’ve found this thread on erlang mailing list, maybe the bug hasn’t been fixed yet? Is there an easy way to find that out?

The way I accept connections:

  def accept(listen_socket, server, timeout) do
    case :ssl.transport_accept(listen_socket, timeout) do
      {:ok, accept_socket} ->
        GenServer.cast(server, :accepted)
        case :ssl.ssl_accept(accept_socket, timeout) do
          :ok -> {:ok, accept_socket}
          {:error, :closed} -> {:error, :econnaborted}
          {:error, reason} -> {:error, reason}
      {:error, reason} ->
        {:error, reason}

I’ve noticed I’m getting {:error, {:tls_alert, 'record overflow'}} in :ssl.ssl_accept(accept_socket, timeout) above. Maybe there is a problem with the keys I’m using …

openssl s_client -dtls1 -connect -debug also doesn’t work.

So it seems it’s not important.

openssl s_client -dtls1 -connect -debug does work with just running

{:ok, listen_socket} = :ssl.listen(8089, [:binary] ++ [
  ip: {0, 0, 0, 0},
  protocol: :dtls,
  keyfile: "priv/server.key",
  certfile: "priv/server.pem",
  active: false

{:ok, accept_socket} = :ssl.transport_accept(listen_socket)

:ok = :ssl.ssl_accept(accept_socket)

:ssl.send(accept_socket, "hello\n")

It doesn’t work with a browser though. RTCPeerConnection’s iceConnectionState becomes "failed".

# same as above to setup a listen_socket and an accept_socket
iex(10)> :ssl.ssl_accept(accept_socket)
{:error, {:tls_alert, 'record overflow'}}
iex(11)> :ssl.send(accept_socket, "hello\n")
{:error, :closed}

I’ve posted on erlang’s mailing list and it seems that the problem here are STUN binding requests. They come to the same port that :ssl listens on. Hence the error.

And the #Port<...> in :sslsocket

iex(4)> {:ok, {:sslsocket, {:gen_udp, {_, {_, port}}, _}, _} = accept_socket} = :ssl.transport_accept(listen_socket)
  {:gen_udp, {#PID<0.116.0>, {{{192, 168, 1, 34}, 55602}, #Port<0.1754>}},
   :dtls_connection}, #PID<0.118.0>}}

doesn’t seem to work with :gen_udp

iex(5)> :gen_udp.recv(port, 0)
{:error, :einval}

so now I don’t know how to handle STUN packets first and then switch to handling DTLS packets on the same port.