Skip to content

Commit

Permalink
Split protocols from socket levels
Browse files Browse the repository at this point in the history
Add a new NIF for retrieving the integer protocol values using atoms.
For socket levels in getsockopt/4 and setsockopt/4, first search
socket_level/1 before checking socket_protocol/1.

socket_protocol/1 duplicates the hard coded values provided by
protocol/1. Since protocol/1 is not exported and is used only with
open/1, it can be replaced with:

    protocol(ip) -> socket_protocol('IPPROTO_IP');
    protocol(icmp) -> socket_protocol('IPPROTO_ICMP');
    protocol(tcp) -> socket_protocol('IPPROTO_TCP');
    ...

Or even:

    protocol(Constant) ->
        socket_protocol(list_to_atom("IPPROTO_" ++
                    string:to_upper(atom_to_list(Constant)))).
  • Loading branch information
msantos committed Jun 8, 2015
1 parent 1f35267 commit e77a6a4
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 3 deletions.
41 changes: 41 additions & 0 deletions c_src/procket.c
Expand Up @@ -1058,6 +1058,45 @@ nif_socket_optname(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return atom_undefined;
}

static ERL_NIF_TERM
nif_socket_protocols(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
const struct procket_define *p = NULL;
ERL_NIF_TERM list = {0};

list = enif_make_list(env, 0);

for (p = procket_socket_protocol; p->key != NULL; p++) {
list = enif_make_list_cell(
env,
enif_make_tuple2(
env,
enif_make_atom(env, p->key),
enif_make_uint(env, p->val)
),
list);
}

return list;
}

static ERL_NIF_TERM
nif_socket_protocol(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
char buf[256] = {0};
const struct procket_define *p = NULL;

if (!enif_get_atom(env, argv[0], buf, sizeof(buf), ERL_NIF_LATIN1))
return enif_make_badarg(env);

for (p = procket_socket_protocol; p->key != NULL; p++) {
if (!strcmp(buf, p->key))
return enif_make_int(env, p->val);
}

return atom_undefined;
}

/* 0: errno */
static ERL_NIF_TERM
nif_errno_id(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
Expand Down Expand Up @@ -1124,8 +1163,10 @@ static ErlNifFunc nif_funcs[] = {

{"socket_level", 0, nif_socket_levels},
{"socket_optname", 0, nif_socket_optnames},
{"socket_protocol", 0, nif_socket_protocols},
{"socket_level", 1, nif_socket_level},
{"socket_optname", 1, nif_socket_optname},
{"socket_protocol", 1, nif_socket_protocol},

{"errno_id", 1, nif_errno_id}
};
Expand Down
6 changes: 5 additions & 1 deletion c_src/procket_constants.h
Expand Up @@ -3,7 +3,7 @@ struct procket_define {
int val;
};

const struct procket_define procket_socket_level[] = {
const struct procket_define procket_socket_protocol[] = {
#ifdef IPPROTO_AH
{"IPPROTO_AH", IPPROTO_AH},
#endif
Expand Down Expand Up @@ -259,6 +259,10 @@ const struct procket_define procket_socket_level[] = {
#ifdef IPPROTO_XTP
{"IPPROTO_XTP", IPPROTO_XTP},
#endif
{NULL, -1}
};

const struct procket_define procket_socket_level[] = {
#ifdef SOL_AAL
{"SOL_AAL", SOL_AAL},
#endif
Expand Down
21 changes: 19 additions & 2 deletions src/procket.erl
Expand Up @@ -61,6 +61,7 @@

socket_level/0, socket_level/1,
socket_optname/0, socket_optname/1,
socket_protocol/0, socket_protocol/1,

errno_id/1
]).
Expand Down Expand Up @@ -187,7 +188,8 @@ sendmsg(_,_,_,_,_) ->
erlang:nif_error(not_implemented).

setsockopt(Socket,Level,Optname,Optval) when is_atom(Level) ->
case socket_level(Level) of
case socket_constant_foreach(Level,
[fun socket_level/1, fun socket_protocol/1]) of
undefined ->
{error,unsupported};
N ->
Expand All @@ -204,7 +206,8 @@ setsockopt(Socket,Level,Optname,Optval) ->
setsockopt_nif(Socket, Level, Optname, Optval).

getsockopt(Socket,Level,Optname,Optval) when is_atom(Level) ->
case socket_level(Level) of
case socket_constant_foreach(Level,
[fun socket_level/1, fun socket_protocol/1]) of
undefined ->
{error,unsupported};
N ->
Expand Down Expand Up @@ -238,9 +241,23 @@ socket_optname() ->
socket_optname(_) ->
erlang:nif_error(not_implemented).

socket_protocol() ->
erlang:nif_error(not_implemented).
socket_protocol(_) ->
erlang:nif_error(not_implemented).

errno_id(_) ->
erlang:nif_error(not_implemented).

socket_constant_foreach(_Constant, []) ->
undefined;
socket_constant_foreach(Constant, [Fun|Funs]) ->
case Fun(Constant) of
undefined ->
socket_constant_foreach(Constant, Funs);
N when is_integer(N) ->
N
end.

%%--------------------------------------------------------------------
%%% Setuid helper
Expand Down

0 comments on commit e77a6a4

Please sign in to comment.