NFIBrokerage / slipstream

A slick WebSocket client for Phoenix Channels
https://hex.pm/packages/slipstream
Apache License 2.0
155 stars 18 forks source link

No match error when attempting to `connect/1` to server #25

Closed jjcarstens closed 3 years ago

jjcarstens commented 3 years ago

According to this comment , I'm supposed to open an issue 👐

I'm trying to experiment with Slipstream to connect to a server via Client-side SSL (This is for connecting Nerves device to nerves-hub.org BTW) and that seems to be causing an error here. I might not have gun options right as it is new to me..

Happy to help test and contribute as needed.

Setup

tls_opts =   [
      cacerts: [
        <<der_encoded_cert, 1, ...>>,
        <<der_encoded_cert, 2, ...>>
      ],
      keyfile: "nerves-hub/poser-x86_64-key.pem",
      certfile: "nerves-hub/poser-x86_64-cert.pem",
      verify: :verify_peer,
      server_name_indication: 'device.nerves-hub.org'
]

uri = "wss://0.0.0.0:4001/socket/websocket"
opts = [
  gun_open_options: %{transport: :tls, tls_opts: tls_opts},
  uri: uri
]

connect(opts)
Produces this error... ``` 12:12:02.649 [error] GenServer #PID<0.490.0> terminating ** (MatchError) no match of right hand side value: {:error, {:options, {:tls_opts, [cacerts: [<>], keyfile: "nerves-hub/poser-x86_64-key.pem", certfile: "nerves-hub/poser-x86_64-cert.pem", verify: :verify_peer, server_name_indication: 'device.nerves-hub.org']}}} (slipstream 0.0.0) lib/slipstream/connection/impl.ex:28: Slipstream.Connection.Impl.connect/1 (slipstream 0.0.0) lib/slipstream/connection/pipeline.ex:179: Slipstream.Connection.Pipeline.handle_message/1 (slipstream 0.0.0) lib/slipstream/connection/pipeline.ex:36: anonymous fn/1 in Slipstream.Connection.Pipeline.handle/2 (slipstream 0.0.0) lib/slipstream/connection/telemetry.ex:29: anonymous fn/2 in Slipstream.Connection.Telemetry.span/2 (telemetry 0.4.2) /home/jonjon/repos/poser/deps/telemetry/src/telemetry.erl:262: :telemetry.span/3 (slipstream 0.0.0) lib/slipstream/connection/telemetry.ex:25: Slipstream.Connection.Telemetry.span/2 (stdlib 3.14) gen_server.erl:689: :gen_server.try_dispatch/4 (stdlib 3.14) gen_server.erl:431: :gen_server.loop/7 Last message: {:continue, :connect} State: %Slipstream.Connection.State{client_pid: #PID<0.488.0>, client_ref: #Reference<0.3467614670.2497970181.119212>, config: %Slipstream.Configuration{gun_open_options: %{protocols: [:http], tls_opts: [cacerts: [<>], keyfile: "nerves-hub/poser-x86_64-key.pem", certfile: "nerves-hub/poser-x86_64-cert.pem", verify: :verify_peer, server_name_indication: 'device.nerves-hub.org'], transport: :tls}, headers: [], heartbeat_interval_msec: 30000, json_parser: Jason, reconnect_after_msec: [10, 50, 100, 150, 200, 250, 500, 1000, 2000, 5000], rejoin_after_msec: [100, 500, 1000, 2000, 5000, 10000], test_mode?: false, uri: %URI{authority: "0.0.0.0:4001", fragment: nil, host: "0.0.0.0", path: "/socket/websocket", port: 4001, query: nil, scheme: "wss", userinfo: nil}}, conn: nil, connection_id: "9e8af19ef7543727", current_ref: 0, current_ref_str: "0", heartbeat_ref: nil, heartbeat_timer: nil, join_params: nil, joins: %{}, leaves: %{}, metadata: %{connection_id: "9e8af19ef7543727", start_time: ~U[2021-02-19 19:12:02.643673Z], start_time_monotonic: -576460751244116933, state: %Slipstream.Connection.State{client_pid: #PID<0.488.0>, client_ref: #Reference<0.3467614670.2497970181.119212>, config: %Slipstream.Configuration{gun_open_options: %{protocols: [:http], tls_opts: [cacerts: [<>], keyfile: "nerves-hub/poser-x86_64-key.pem", certfile: "nerves-hub/poser-x86_64-cert.pem", verify: :verify_peer, server_name_indication: 'device.nerves-hub.org'], transport: :tls}, headers: [], heartbeat_interval_msec: 30000, json_parser: Jason, reconnect_after_msec: [10, 50, 100, 150, 200, 250, 500, 1000, 2000, 5000], rejoin_after_msec: [100, 500, 1000, 2000, 5000, 10000], test_mode?: false, uri: %URI{authority: "0.0.0.0:4001", fragment: nil, host: "0.0.0.0", path: "/socket/websocket", port: 4001, query: nil, scheme: "wss", userinfo: nil}}, conn: nil, connection_id: "9e8af19ef7543727", current_ref: 0, current_ref_str: "0", heartbeat_ref: nil, heartbeat_timer: nil, join_params: nil, joins: %{}, leaves: %{}, metadata: nil, status: :opened, stream_ref: nil, trace_id: "2efa9caa07a01c2b9c0b541007a8b9db"}, trace_id: "2efa9caa07a01c2b9c0b541007a8b9db"}, status: :opened, stream_ref: nil, trace_id: "2efa9caa07a01c2b9c0b541007a8b9db"} ```
jjcarstens commented 3 years ago

FYI, looks like the tls_opts is invalid for some reason. If I change that to transport_opts, then looks like my connection can succeed.

jjcarstens commented 3 years ago

Ah, so it looks like this is using :gun 1.3.3 which defines :gun.opts() type to use the :transport_opts key - see https://ninenines.eu/docs/en/gun/1.3/manual/gun/#_opts

However, I was referencing :gun 2.0 docs, which expects :tls_opts - See https://ninenines.eu/docs/en/gun/2.0/manual/gun/#_opts

I guess I'll leave this issue for posterity and let you decide what to do with it.

the-mikedavis commented 3 years ago

:wave: hello!

I guess I can't say I haven't seen a result other than {:ok, conn} now :grin:

IMHO the gun docs are a bit cryptic in that (1) they point to v2 by default, which is still in release-candidate phase, (2) the types section is in alphabetical order, which kinda hides the t:gun:opts/0 type behind the others, and (3) you can't permalink to each type

I'll close this issue for now and noodle on refacting that initial connection to handle a mismatch more gracefully (it'll probably end up as an invocation of c:Slipstream.handle_disconnect/2)

thanks for opening up this issue! :slightly_smiling_face: