%% -*- mode: erlang; tab-width: 4; indent-tabs-mode: 1; st-rulers: [70] -*- %% vim: ts=4 sw=4 ft=erlang noet %%%------------------------------------------------------------------- %%% @author Andrew Bennett %%% @copyright 2015-2022, Andrew Bennett %%% @doc %%% %%% @end %%% Created : 28 Dec 2015 by Andrew Bennett %%%------------------------------------------------------------------- -module(libsodium). -include("libsodium.hrl"). %% API -export([start/0]). -export([call/2]). -export([call/3]). -export([call/4]). -export([open/0]). -export([close/1]). -define(MAYBE_START_LIBSODIUM(F), try F catch _:_ -> _ = libsodium:start(), F end). %%%=================================================================== %%% API %%%=================================================================== start() -> application:ensure_all_started(?MODULE). call(Namespace, Function) when is_atom(Namespace) andalso is_atom(Function) -> ?MAYBE_START_LIBSODIUM(call(Namespace, Function, {})). call(Namespace, Function, Arguments) when is_atom(Namespace) andalso is_atom(Function) andalso is_tuple(Arguments) -> ?MAYBE_START_LIBSODIUM(call(erlang:whereis(?LIBSODIUM_DRIVER_ATOM), Namespace, Function, Arguments)). call(Port, Namespace, Function, Arguments) when is_port(Port) andalso is_atom(Namespace) andalso is_atom(Function) andalso is_tuple(Arguments) -> driver_call(Port, ?LIBSODIUM_ASYNC_CALL, Namespace, Function, Arguments). open() -> erlang:open_port({spawn_driver, ?LIBSODIUM_DRIVER_NAME}, [binary]). close(P) -> try true = erlang:port_close(P), receive {'EXIT', P, _} -> ok after 0 -> ok end catch _:_ -> erlang:error(badarg) end. %%%------------------------------------------------------------------- %%% Internal functions %%%------------------------------------------------------------------- %% @private driver_call(Port, Command, Namespace, Function, Arguments) -> Tag = erlang:make_ref(), case erlang:port_call(Port, Command, {Tag, Namespace, Function, Arguments}) of Tag -> receive {Tag, Reply} -> Reply end; {Tag, Error} -> Error end.