Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add sendto/4 and bind/2

sendto/4 takes as arguments:
* the socket descriptor
* the buffer to be sent
* flags
* a binary representing a struct sockaddr_*

For example, to send an ICMP echo to 192.168.100.1, assuming the variable
"Packet" holds a valid ICMP packet:

ok = procket:sendto(S, Packet, 0,
    <<
        2:16/native,                    % sin_family: PF_INET
        0:16,                           % sin_port
        192:8, 168:8, 100:8, 1:8,       % sin_addr
        0:64                            % sin_zero
    >>
).

Similarly, bind/2 takes:
* the socket descriptor
* a binary representing a struct sockaddr_*
  • Loading branch information...
commit 74a854e59e72137729b65bc7234d3fe0faeee52e 1 parent a85f8be
@msantos authored
Showing with 35 additions and 30 deletions.
  1. +30 −28 c_src/procket.c
  2. +5 −2 src/procket.erl
View
58 c_src/procket.c
@@ -178,48 +178,30 @@ nif_recvfrom(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
}
-/* 0: socket, 1: buffer, 2: flags, 3: address
- * 4: port, 5: family
- */
+/* 0: socket, 1: buffer, 2: flags, 3: struct sockaddr */
static ERL_NIF_TERM
nif_sendto(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
int sockfd = -1;
int flags = 0;
- char address[1024]; /* XXX IPv4 */
- struct in_addr in;
- struct sockaddr_in sa = {0};
- in_port_t port = 0;
- int family = 0;
ErlNifBinary buf;
+ ErlNifBinary sa;
+
if (!enif_get_int(env, argv[0], &sockfd))
return enif_make_badarg(env);
- if (!enif_inspect_iolist_as_binary(env, argv[1], &buf))
+ if (!enif_inspect_binary(env, argv[1], &buf))
return enif_make_badarg(env);
if (!enif_get_int(env, argv[2], &flags))
return enif_make_badarg(env);
- if (enif_get_string(env, argv[3], address, sizeof(address), ERL_NIF_LATIN1) < 1)
- return enif_make_badarg(env);
-
- if (!enif_get_int(env, argv[4], (int *)&port))
- return enif_make_badarg(env);
-
- if (!enif_get_int(env, argv[5], &family))
+ if (!enif_inspect_binary(env, argv[3], &sa))
return enif_make_badarg(env);
- if (inet_aton(address, &in) < 0)
- return enif_make_badarg(env);
-
- sa.sin_family = family;
- sa.sin_port = htons(port);
- sa.sin_addr.s_addr = in.s_addr;
-
- if (sendto(sockfd, buf.data, buf.size, flags, (struct sockaddr *)&sa, sizeof(sa)) == -1)
+ if (sendto(sockfd, buf.data, buf.size, flags, (struct sockaddr *)sa.data, sa.size) == -1)
return enif_make_tuple(env, 2,
atom_error,
enif_make_tuple(env, 2,
@@ -230,6 +212,27 @@ nif_sendto(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
}
+/* 0: socket descriptor, 1: struct sockaddr */
+ static ERL_NIF_TERM
+nif_bind(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ int s = -1;
+ ErlNifBinary sa;
+
+
+ if (!enif_get_int(env, argv[0], &s))
+ return enif_make_badarg(env);
+
+ if (!enif_inspect_binary(env, argv[1], &sa))
+ return enif_make_badarg(env);
+
+ if (bind(s, (struct sockaddr *)sa.data, sa.size) < 0)
+ return error_tuple(env, strerror(errno));
+
+ return atom_ok;
+}
+
+
static ERL_NIF_TERM
error_tuple(ErlNifEnv *env, char *err)
{
@@ -254,10 +257,9 @@ static ErlNifFunc nif_funcs[] = {
{"open", 1, nif_open},
{"poll", 1, nif_poll},
{"close", 2, nif_close},
- /*
- {"sendto", 6, nif_sendto},
- */
- {"recvfrom", 2, nif_recvfrom}
+ {"bind", 2, nif_bind},
+ {"recvfrom", 2, nif_recvfrom},
+ {"sendto", 4, nif_sendto}
};
ERL_NIF_INIT(procket, nif_funcs, load, NULL, NULL, NULL)
View
7 src/procket.erl
@@ -32,7 +32,7 @@
-export([
init/0,open/1,poll/1,close/2,listen/1,listen/2,
- recvfrom/2,sendto/6
+ recvfrom/2,sendto/4,bind/2
]).
-export([make_args/2,progname/0]).
@@ -54,10 +54,13 @@ poll(_) ->
close(_,_) ->
erlang:error(not_implemented).
+bind(_,_) ->
+ erlang:error(not_implemented).
+
recvfrom(_,_) ->
erlang:error(not_implemented).
-sendto(_,_,_,_,_,_) ->
+sendto(_,_,_,_) ->
erlang:error(not_implemented).
listen(Port) ->
Please sign in to comment.
Something went wrong with that request. Please try again.