jnnks

jnnks

I want to use the library https://github.com/qzhuyan/quicer which is written in Erlang.
The readme contains a sample snippet:

application:ensure_all_started(quicer),
Port = 4567,
LOptions = [ {certfile, "cert.pem"}
           , {keyfile,  "key.pem"}
           , {alpn, ["sample"]}
           , {peer_bidi_stream_count, 1}
             ],
{ok, L} = quicer:listen(Port, LOptions),
{ok, Conn} = quicer:accept(L, [], 120000),
{ok, Conn} = quicer:handshake(Conn),
{ok, Stm} = quicer:accept_stream(Conn, []),
receive {quic, <<"ping">>, Stm, _Props} -> ok end,
{ok, 4} = quicer:send(Stm, <<"pong">>),
quicer:close_listener(L).

which I translated to the following:

:application.ensure_all_started(:quicer)

    port = 4567
    l_options = [
      {:certfile, "cert.pem"},
      {:keyfile, "key.pem"},
      {:alpn, ["sample"]},
      {:peer_bidi_stream_count, 1}
    ]
    # {:error, :badarg}
    {:ok, listener} = :quicer.listen(port, l_options)
    {:ok, conn} = :quicer.accept(listener, [], 120_000)
    {:ok, conn} = :quicer.handshake(conn)
    {:ok, stm} = :quicer.accept_stream(conn, [])

    receive do
      {:quic, <<"ping">>, stm, _props} -> :ok
    end

    {:ok, 4} = :quicer.send(stm, <<"pong">>)
    :quicer.close_listener(listener)

Something seems to be wrong, as there is a badarg (marked above).
ElixirLS Dialyzer is reporting the following:

The call quicer:listen
         (_port@1 :: 4567,
          _l_options@1 ::
              [{'alpn', [<<_:48>>, ...]} |
               {'certfile', <<_:64>>} |
               {'keyfile', <<_:56>>} |
               {'peer_bidi_stream_count', 1},
               ...]) breaks the contract 
          (listen_on(), listen_opts()) ->
             {'ok', listener_handler()} |
             {'error', 'listener_open_error', atom_reason()} |
             {'error', 'listener_start_error', atom_reason()}

What am I missing?
PS: ChatGPT came to the same translation :slight_smile:

Showing Posts 1 to 10

paulanthonywilson

paulanthonywilson

I think the problem is the strings. Remember the thing where strings are lists of characters in Erlang?

Try using single quotes in place of double quotes in the translation. eg

{:certfile, 'cert.pem'}
jnnks

jnnks OP

Thanks for the hint, but the error is still the same.
I have also tried String.to_charlist as suggested here: membrane_quic_plugin/lib/membrane_quic_plugin/server.ex at f50f3658f6a18f5791398ade8102dfc9f08f11fd · mickel8/membrane_quic_plugin · GitHub. That was the only use for that library in Elixir on Github that I could find.
Even an empty list will still raise the same error.

paulanthonywilson

paulanthonywilson

Oh weird. I got slightly nerdsniped and tried in Elixir

:quicer.listen(4567,[certfile: 'cert.pem', keyfile: 'key.pem', alpn: ['sample'], peer_bidi_stream_count: 1])  

I got {:error, :config_error, :tls_error} rather than a bad arg, which seems fair enough as those SSL certificate files and keys didn’t actually exist for me.

jnnks

jnnks OP

Even with incorrect paths, the error is still badarg for me :smiley:
I am using OTP24, do you know if there are any breaking changes since 22 (mentioned as min requirement in quicer readme) ?

paulanthonywilson

paulanthonywilson

Very strange. I can get a badarg by changing (say) the :keyfile value to a binary string. ¯\(ツ)/¯

Seems unlikely. I was using otp 25.

BradS2S

BradS2S

BradS2S

BradS2S

Looking over the error again, I think it is as simple as not handling error outcomes

Set up a case statement for all three contracts. Right note you only handle the success outcome.

{'ok', listener_handler()} 
 {:'error', 'listener_open_error', atom_reason()} 
 {'error', 'listener_start_error', atom_reason()}
al2o3cr

al2o3cr

Like in the last ChatGPT Erlang-to-Elixir translation, the robot doesn’t do a good job spotting the difference between binaries and charlists. :man_shrugging:

Dialyzer is complaining about the binaries in your options, since listen_opts is defined as:

https://github.com/qzhuyan/quicer/blob/b93b5a8116e57ae5a9d8ac3fbf8d15653ce2ceba/include/quicer_types.hrl#L75-L87

alpn() is defined as string() - so charlists

file:filename() is defined in stdlib as… string() - so charlists

jnnks

jnnks OP

@BradS2S
Erlang/OTP 24 [erts-12.3.2.7], Elixir (1.14.2),
rlang/OTP 25 [erts-13.1.5], Elixir (1.15.0-dev)

@al2o3cr So then I should use:

:quicer.listen(4567,
  certfile: String.to_charlist("./cert.pem"),
  keyfile: String.to_charlist("./key.pem"),
  ...
)

That also does not work, still badarg. Even the empty list is a badarg. Could the error originate from inside the library/NIF somewhere and just appears to be from the listen call?

al2o3cr

al2o3cr

There are many places inside of :quicer.listen’s NIF that can return {:error, :badarg}:

https://github.com/qzhuyan/quicer/blob/b93b5a8116e57ae5a9d8ac3fbf8d15653ce2ceba/c_src/quicer_listener.c#L251-L455

Passing an empty list of options results in {:error, :badarg} because of checks for required parameters, for instance the ones on line 302-316.

One other thing that jumps out: the change to add support for certfile and keyfile (instead of just cert and key) isn’t in a released package, it was just added a bit more than a month ago. If you’ve installed quicer from Hex, try using cert and key (the old names) instead.

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New
dillonoconnor
Is there any way to avoid the Hologram compiler running when using iex? It seems like the front-end code could potentially be disregarded...
New
thiagogsr
** (ArgumentError) expected :max_attempts to be a positive integer, got: {:@, [line: 10, column: 19], [{:max_attempts, [line: 10, column:...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews