-module(kafein). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/kafein.gleam"). -export([protocol_versions/2, alpn/2, cacert_file/2, cipher_suites/2, depth/2, verify/2, certificate/2, certificates/2, curves/2, handshake_pause/1, server_name_indication/2, send_builder/2, send/2, shutdown/1, export_key_materials/4, export_key_material/4, handshake_cancel/1, 'receive'/2, receive_exact/3, receive_next_packet_as_message/1, select_ssl_messages/2, wrap/2, handshake_continue/3]). -export_type([ssl_socket/0, tls_alert_kind/0, curve/0, error/0, export_key_materials_error/0, protocol_version/0, verification_type/0, certificate/0, wrap_options/0, ssl_message/0, internal_tls_option/0, gen_tcp_option/0, active_type/0, handshake_type/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type ssl_socket() :: any(). -type tls_alert_kind() :: close_notify | unexpected_message | bad_record_mac | record_overflow | handshake_failure | bad_certificate | unsupported_certificate | certificate_revoked | certificate_expired | certificate_unknown | illegal_parameter | unknown_ca | access_denied | decode_error | decrypt_error | export_restriction | protocol_version | insufficient_security | internal_error | inappropriate_fallback | user_canceled | no_renegotiation | unsupported_extension | certificate_unobtainable | unrecognized_name | bad_certificate_status_response | bad_certificate_hash_value | unknown_psk_identity | no_application_protocol. -type curve() :: x25519 | x448 | secp521r1 | brainpool_p512r1 | brainpool_p384r1 | secp384r1 | brainpool_p256r1 | secp256r1 | sect571r1 | sect571k1 | sect409k1 | sect409r1 | sect283k1 | sect283r1 | secp256k1 | sect239k1 | sect233k1 | sect233r1 | secp224k1 | secp224r1 | sect193r1 | sect193r2 | secp192k1 | secp192r1 | sect163k1 | sect163r1 | sect163r2 | secp160k1 | secp160r1 | secp160r2. -type error() :: closed | timeout | {other, gleam@dynamic:dynamic_()} | {posix_error, mug:error()} | {cipher_suite_not_recognized, binary()} | {tls_alert, tls_alert_kind(), binary()}. -type export_key_materials_error() :: exporter_master_secret_already_consumed | bad_input. -type protocol_version() :: tlsv1 | tlsv1m1 | tlsv1m2 | tlsv1m3. -type verification_type() :: verify_none | verify_peer. -type certificate() :: {certificate, binary(), binary(), gleam@option:option(fun(() -> binary()))}. -type wrap_options() :: {wrap_options, list(protocol_version()), list(binary()), gleam@option:option(binary()), list(binary()), integer(), verification_type(), list(certificate()), list(curve()), boolean(), gleam@option:option(binary())}. -type ssl_message() :: {packet, ssl_socket(), bitstring()} | {socket_closed, ssl_socket()} | {ssl_error, ssl_socket(), error()}. -type internal_tls_option() :: {versions, list(gleam@erlang@atom:atom_())} | {cacerts, gleam@dynamic:dynamic_()} | {depth, integer()} | {verify, verification_type()} | {ciphers, list(gleam@dynamic:dynamic_())} | {alpn_advertised_protocols, list(binary())} | {cacertfile, binary()} | {certs_keys, list(gleam@dict:dict(binary(), gleam@dynamic:dynamic_()))} | {handshake, handshake_type()} | {eccs, list(curve())} | {server_name_indication, gleam@dynamic:dynamic_()}. -type gen_tcp_option() :: {active, active_type()}. -type active_type() :: once. -type handshake_type() :: hello | full. -file("src/kafein.gleam", 170). ?DOC(" Set protocol versions for upgrade.\n"). -spec protocol_versions(wrap_options(), list(protocol_version())) -> wrap_options(). protocol_versions(Options, Protocol_versions) -> {wrap_options, Protocol_versions, erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options), erlang:element(7, Options), erlang:element(8, Options), erlang:element(9, Options), erlang:element(10, Options), erlang:element(11, Options)}. -file("src/kafein.gleam", 178). ?DOC(" Set supported ALPN protocols.\n"). -spec alpn(wrap_options(), list(binary())) -> wrap_options(). alpn(Options, Alpn) -> {wrap_options, erlang:element(2, Options), Alpn, erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options), erlang:element(7, Options), erlang:element(8, Options), erlang:element(9, Options), erlang:element(10, Options), erlang:element(11, Options)}. -file("src/kafein.gleam", 183). ?DOC(" Set cacert file used for TLS.\n"). -spec cacert_file(wrap_options(), binary()) -> wrap_options(). cacert_file(Options, Cacert_file) -> {wrap_options, erlang:element(2, Options), erlang:element(3, Options), {some, Cacert_file}, erlang:element(5, Options), erlang:element(6, Options), erlang:element(7, Options), erlang:element(8, Options), erlang:element(9, Options), erlang:element(10, Options), erlang:element(11, Options)}. -file("src/kafein.gleam", 191). ?DOC(" Set ciphers suites used for TLS.\n"). -spec cipher_suites(wrap_options(), list(binary())) -> wrap_options(). cipher_suites(Options, Cipher_suites) -> {wrap_options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), Cipher_suites, erlang:element(6, Options), erlang:element(7, Options), erlang:element(8, Options), erlang:element(9, Options), erlang:element(10, Options), erlang:element(11, Options)}. -file("src/kafein.gleam", 199). ?DOC(" Set depth of allowed certificate chain.\n"). -spec depth(wrap_options(), integer()) -> wrap_options(). depth(Options, Depth) -> {wrap_options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), Depth, erlang:element(7, Options), erlang:element(8, Options), erlang:element(9, Options), erlang:element(10, Options), erlang:element(11, Options)}. -file("src/kafein.gleam", 204). ?DOC(" Set verification type for certificate.\n"). -spec verify(wrap_options(), verification_type()) -> wrap_options(). verify(Options, Verify) -> {wrap_options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options), Verify, erlang:element(8, Options), erlang:element(9, Options), erlang:element(10, Options), erlang:element(11, Options)}. -file("src/kafein.gleam", 212). ?DOC(" Add certificate used for TLS.\n"). -spec certificate(wrap_options(), certificate()) -> wrap_options(). certificate(Options, Cert) -> {wrap_options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options), erlang:element(7, Options), lists:append(erlang:element(8, Options), [Cert]), erlang:element(9, Options), erlang:element(10, Options), erlang:element(11, Options)}. -file("src/kafein.gleam", 223). ?DOC(" Add list of certificates used for TLS.\n"). -spec certificates(wrap_options(), list(certificate())) -> wrap_options(). certificates(Options, Certs) -> {wrap_options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options), erlang:element(7, Options), lists:append(erlang:element(8, Options), Certs), erlang:element(9, Options), erlang:element(10, Options), erlang:element(11, Options)}. -file("src/kafein.gleam", 231). ?DOC(" Set curves used for TLS.\n"). -spec curves(wrap_options(), list(curve())) -> wrap_options(). curves(Options, Curves) -> {wrap_options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options), erlang:element(7, Options), erlang:element(8, Options), Curves, erlang:element(10, Options), erlang:element(11, Options)}. -file("src/kafein.gleam", 236). ?DOC(" Make handshake pause after HELLO.\n"). -spec handshake_pause(wrap_options()) -> wrap_options(). handshake_pause(Options) -> {wrap_options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options), erlang:element(7, Options), erlang:element(8, Options), erlang:element(9, Options), true, erlang:element(11, Options)}. -file("src/kafein.gleam", 241). ?DOC(" Set SNI.\n"). -spec server_name_indication(wrap_options(), binary()) -> wrap_options(). server_name_indication(Options, Name) -> {wrap_options, erlang:element(2, Options), erlang:element(3, Options), erlang:element(4, Options), erlang:element(5, Options), erlang:element(6, Options), erlang:element(7, Options), erlang:element(8, Options), erlang:element(9, Options), erlang:element(10, Options), {some, Name}}. -file("src/kafein.gleam", 321). -spec send_builder(ssl_socket(), gleam@bytes_tree:bytes_tree()) -> {ok, nil} | {error, mug:error()}. send_builder(Socket, Data) -> kafein_ffi:send(Socket, Data). -file("src/kafein.gleam", 316). -spec send(ssl_socket(), bitstring()) -> {ok, nil} | {error, mug:error()}. send(Socket, Data) -> kafein_ffi:send(Socket, gleam@bytes_tree:from_bit_array(Data)). -file("src/kafein.gleam", 362). -spec shutdown(ssl_socket()) -> {ok, nil} | {error, mug:error()}. shutdown(Socket) -> kafein_ffi:shutdown(Socket). -file("src/kafein.gleam", 299). ?DOC( " Export some of key materials.\n" "\n" " Returns an error if exporting was failed.\n" ). -spec export_key_materials( ssl_socket(), list(bitstring()), list(gleam@option:option(bitstring())), list(integer()) ) -> {ok, list(bitstring())} | {error, export_key_materials_error()}. export_key_materials(Socket, Labels, Contexts, Lengths) -> Contexts@1 = gleam@list:map( Contexts, fun(Wrap_context) -> case Wrap_context of {some, Context} -> gleam_stdlib:identity(Context); none -> _pipe = erlang:binary_to_atom(<<"no_context"/utf8>>), gleam_erlang_ffi:identity(_pipe) end end ), ssl:export_key_materials(Socket, Labels, Contexts@1, Lengths). -file("src/kafein.gleam", 281). ?DOC( " Export a single key material.\n" "\n" " Returns an error if exporting was failed.\n" ). -spec export_key_material( ssl_socket(), bitstring(), gleam@option:option(bitstring()), integer() ) -> {ok, bitstring()} | {error, export_key_materials_error()}. export_key_material(Socket, Label, Context, Length) -> gleam@result:'try'( export_key_materials(Socket, [Label], [Context], [Length]), fun(Key_materials) -> case gleam@list:first(Key_materials) of {error, _} -> {error, bad_input}; {ok, Key_material} -> {ok, Key_material} end end ). -file("src/kafein.gleam", 274). ?DOC( " Cancel the handshake operation.\n" "\n" " Returns an error if cancellation was failed.\n" ). -spec handshake_cancel(ssl_socket()) -> {ok, nil} | {error, error()}. handshake_cancel(Socket) -> kafein_ffi:handshake_cancel(Socket). -file("src/kafein.gleam", 326). -spec 'receive'(ssl_socket(), integer()) -> {ok, bitstring()} | {error, mug:error()}. 'receive'(Socket, Timeout) -> ssl:recv(Socket, 0, Timeout). -file("src/kafein.gleam", 333). -spec receive_exact(ssl_socket(), integer(), integer()) -> {ok, bitstring()} | {error, mug:error()}. receive_exact(Socket, Size, Timeout) -> ssl:recv(Socket, Size, Timeout). -file("src/kafein.gleam", 341). -spec receive_next_packet_as_message(ssl_socket()) -> nil. receive_next_packet_as_message(Socket) -> ssl:setopts(Socket, [{active, once}]), nil. -file("src/kafein.gleam", 346). -spec select_ssl_messages( gleam@erlang@process:selector(HTB), fun((ssl_message()) -> HTB) ) -> gleam@erlang@process:selector(HTB). select_ssl_messages(Selector, Mapper) -> Ssl = erlang:binary_to_atom(<<"ssl"/utf8>>), Closed = erlang:binary_to_atom(<<"ssl_closed"/utf8>>), Error = erlang:binary_to_atom(<<"ssl_error"/utf8>>), Map_message = fun(Msg) -> Mapper(kafein_ffi:coerce_ssl_message(Msg)) end, _pipe = Selector, _pipe@1 = gleam@erlang@process:select_record(_pipe, Ssl, 2, Map_message), _pipe@2 = gleam@erlang@process:select_record( _pipe@1, Closed, 1, Map_message ), gleam@erlang@process:select_record(_pipe@2, Error, 2, Map_message). -file("src/kafein.gleam", 391). -spec coerce_options(wrap_options()) -> {ok, list(internal_tls_option())} | {error, error()}. coerce_options(Options) -> gleam@result:'try'( kafein_ffi:strs_to_suites(erlang:element(5, Options)), fun(Ciphers) -> _pipe@8 = [{versions, gleam@list:map( erlang:element(2, Options), fun(Ver) -> erlang:binary_to_atom(case Ver of tlsv1 -> <<"tlsv1"/utf8>>; tlsv1m1 -> <<"tlsv1.1"/utf8>>; tlsv1m2 -> <<"tlsv1.2"/utf8>>; tlsv1m3 -> <<"tlsv1.3"/utf8>> end) end )}, {cacerts, public_key:cacerts_get()}, {depth, erlang:element(6, Options)}, {verify, erlang:element(7, Options)}, {certs_keys, gleam@list:map( erlang:element(8, Options), fun(Cert) -> _pipe = maps:new(), _pipe@2 = gleam@dict:insert( _pipe, <<"certfile"/utf8>>, begin _pipe@1 = erlang:element(2, Cert), gleam_stdlib:identity(_pipe@1) end ), _pipe@4 = gleam@dict:insert( _pipe@2, <<"keyfile"/utf8>>, begin _pipe@3 = erlang:element(3, Cert), gleam_stdlib:identity(_pipe@3) end ), (fun(D) -> case erlang:element(4, Cert) of {some, Func} -> _pipe@5 = D, gleam@dict:insert( _pipe@5, <<"password"/utf8>>, begin _pipe@6 = Func, kafein_ffi:unsafe_cast(_pipe@6) end ); none -> D end end)(_pipe@4) end )}, {handshake, case erlang:element(10, Options) of true -> hello; false -> full end}, {server_name_indication, case erlang:element(11, Options) of {some, Name} -> gleam_stdlib:identity(Name); none -> _pipe@7 = erlang:binary_to_atom(<<"disable"/utf8>>), gleam_erlang_ffi:identity(_pipe@7) end}], _pipe@9 = lists:append(_pipe@8, case erlang:element(4, Options) of {some, Cacert_file} -> [{cacertfile, Cacert_file}]; none -> [] end), _pipe@10 = lists:append(_pipe@9, case Ciphers of [] -> []; _ -> [{ciphers, Ciphers}] end), _pipe@11 = lists:append(_pipe@10, case erlang:element(3, Options) of [] -> []; Alpn -> [{alpn_advertised_protocols, Alpn}] end), _pipe@12 = lists:append(_pipe@11, case erlang:element(9, Options) of [] -> []; Eccs -> [{eccs, Eccs}] end), {ok, _pipe@12} end ). -file("src/kafein.gleam", 251). ?DOC( " Upgrades a TCP connection to SSL connection.\n" "\n" " Returns an error if upgrading was failed.\n" ). -spec wrap(wrap_options(), mug:socket()) -> {ok, ssl_socket()} | {error, error()}. wrap(Options, Socket) -> gleam@result:'try'( coerce_options(Options), fun(Connect_options) -> kafein_ffi:wrap(Socket, Connect_options) end ). -file("src/kafein.gleam", 262). ?DOC( " Continue the handshake with specified wrap options.\n" "\n" " Returns an error if handshake was failed.\n" ). -spec handshake_continue(wrap_options(), ssl_socket(), integer()) -> {ok, ssl_socket()} | {error, error()}. handshake_continue(Options, Socket, Timeout) -> gleam@result:'try'( coerce_options(Options), fun(Handshake_options) -> ssl:handshake_continue(Socket, Handshake_options, Timeout) end ).