aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2018-07-31 12:53:52 +0200
committerMicael Karlberg <[email protected]>2018-09-18 14:50:18 +0200
commitd4c6b555aea77198d662822c7f5a134a16cff8af (patch)
tree51fbbc59bd11e850f866b95f41cccaebdc3f186c
parent165666d8b8b1b21ffaf43ac436cfc1657ba83649 (diff)
downloadotp-d4c6b555aea77198d662822c7f5a134a16cff8af.tar.gz
otp-d4c6b555aea77198d662822c7f5a134a16cff8af.tar.bz2
otp-d4c6b555aea77198d662822c7f5a134a16cff8af.zip
[socket-nif] Debugged and stuff
It seems to work, with atleast some of the cmsg options. More testing needed... OTP-14831
-rw-r--r--erts/emulator/nifs/common/socket_nif.c44
-rw-r--r--erts/emulator/nifs/common/socket_tarray.c8
-rw-r--r--erts/emulator/nifs/common/socket_tarray.h2
-rw-r--r--erts/emulator/nifs/common/socket_util.c104
-rw-r--r--erts/emulator/nifs/common/socket_util.h2
-rw-r--r--lib/kernel/test/socket_server.erl45
6 files changed, 159 insertions, 46 deletions
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index 6b6ddb29ca..205b3335e1 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -1875,6 +1875,7 @@ static ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
int read,
int saveErrno,
struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
ErlNifBinary* ctrlBufP,
ERL_NIF_TERM recvRef);
@@ -4102,7 +4103,7 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
- if ((argc != 4) ||
+ if ((argc != 5) ||
!enif_get_resource(env, argv[0], sockets, (void**) &descP) ||
!GET_UINT(env, argv[2], &bufSz) ||
!GET_UINT(env, argv[3], &ctrlSz) ||
@@ -4170,14 +4171,15 @@ ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
unsigned int addrLen;
ssize_t read;
int save_errno;
- ErlNifBinary buf, ctrl;
int bufSz = (bufLen ? bufLen : descP->rBufSz);
int ctrlSz = (ctrlLen ? ctrlLen : descP->rCtrlSz);
struct msghdr msgHdr;
- struct iovec iov[1]; // Shall we always use 1?
+ struct iovec iov[1]; // Shall we always use 1?
+ ErlNifBinary data[1]; // Shall we always use 1?
+ ErlNifBinary ctrl;
SocketAddress addr;
- SSDBG( descP, ("SOCKET", "nrecvfrom -> entry with"
+ SSDBG( descP, ("SOCKET", "nrecvmsg -> entry with"
"\r\n bufSz: %d (%d)"
"\r\n ctrlSz: %d (%d)"
"\r\n flags: %d"
@@ -4197,7 +4199,7 @@ ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
/* Allocate the (msg) data buffer:
*/
- if (!ALLOC_BIN(bufSz, &buf))
+ if (!ALLOC_BIN(bufSz, &data[0]))
return esock_make_error(env, atom_exalloc);
/* Allocate the ctrl (buffer):
@@ -4214,8 +4216,8 @@ ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
sys_memzero((char*) &addr, addrLen);
sys_memzero((char*) &msgHdr, sizeof(msgHdr));
- iov[0].iov_base = buf.data;
- iov[0].iov_len = buf.size;
+ iov[0].iov_base = data[0].data;
+ iov[0].iov_len = data[0].size;
msgHdr.msg_name = &addr;
msgHdr.msg_namelen = addrLen;
@@ -4234,7 +4236,8 @@ ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
read,
save_errno,
&msgHdr,
- &ctrl, // Needed for ctrl header decode
+ data, // Needed for iov encode
+ &ctrl, // Needed for ctrl header encode
recvRef);
}
@@ -10598,6 +10601,7 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
int read,
int saveErrno,
struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
ErlNifBinary* ctrlBufP,
ERL_NIF_TERM recvRef)
{
@@ -10680,11 +10684,24 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
*/
if ((xres = esock_encode_msghdr(env, read,
- msgHdrP, ctrlBufP,
- &eMsgHdr)) != NULL)
+ msgHdrP, dataBufP, ctrlBufP,
+ &eMsgHdr)) != NULL) {
+
+ SSDBG( descP,
+ ("SOCKET",
+ "recvfrom_check_result -> "
+ "(msghdr) encode failed: %s\r\n", xres) );
+
return esock_make_error_str(env, xres);
- else
+ } else {
+
+ SSDBG( descP,
+ ("SOCKET",
+ "recvfrom_check_result -> "
+ "(msghdr) encode ok: %T\r\n", eMsgHdr) );
+
return esock_make_ok2(env, eMsgHdr);
+ }
}
}
@@ -12414,8 +12431,9 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
esock_atom_flowinfo = MKA(env, "flowinfo");
esock_atom_inet = MKA(env, "inet");
esock_atom_inet6 = MKA(env, "inet6");
- esock_atom_ip = MKA(env, "iov");
- esock_atom_ipv6 = MKA(env, "ipvp");
+ esock_atom_iov = MKA(env, "iov");
+ esock_atom_ip = MKA(env, "ip");
+ esock_atom_ipv6 = MKA(env, "ipv6");
esock_atom_level = MKA(env, "level");
esock_atom_local = MKA(env, "local");
esock_atom_loopback = MKA(env, "loopback");
diff --git a/erts/emulator/nifs/common/socket_tarray.c b/erts/emulator/nifs/common/socket_tarray.c
index bf37e5bc0e..a327e014c4 100644
--- a/erts/emulator/nifs/common/socket_tarray.c
+++ b/erts/emulator/nifs/common/socket_tarray.c
@@ -63,13 +63,13 @@ void* esock_tarray_create(uint32_t sz)
{
SocketTArrayInt* tarrayP;
- ESOCK_ASSERT( (sz == 0) );
+ ESOCK_ASSERT( (sz > 0) );
tarrayP = MALLOC(sizeof(SocketTArrayInt));
- ESOCK_ASSERT( (tarrayP == NULL) );
+ ESOCK_ASSERT( (tarrayP != NULL) );
tarrayP->array = MALLOC(sz * sizeof(ERL_NIF_TERM));
- ESOCK_ASSERT( (tarrayP->array == NULL) );
+ ESOCK_ASSERT( (tarrayP->array != NULL) );
tarrayP->sz = sz;
tarrayP->idx = 0;
@@ -131,7 +131,7 @@ void esock_tarray_ensure_fits(SocketTArrayInt* taP, uint32_t needs)
uint32_t newSz = (needs < taP->sz) ? 2*taP->sz : 2*needs;
void* mem = REALLOC(taP->array, newSz * sizeof(ERL_NIF_TERM));
- ESOCK_ASSERT( (mem == NULL) );
+ ESOCK_ASSERT( (mem != NULL) );
taP->sz = newSz;
taP->array = (ERL_NIF_TERM*) mem;
diff --git a/erts/emulator/nifs/common/socket_tarray.h b/erts/emulator/nifs/common/socket_tarray.h
index 2e9506d288..4d78d2ccb7 100644
--- a/erts/emulator/nifs/common/socket_tarray.h
+++ b/erts/emulator/nifs/common/socket_tarray.h
@@ -33,7 +33,7 @@ extern SocketTArray esock_tarray_create(uint32_t sz);
extern void esock_tarray_delete(SocketTArray ta);
extern uint32_t esock_tarray_sz(SocketTArray ta);
extern void esock_tarray_add(SocketTArray ta, ERL_NIF_TERM t);
-extern void esock_tarray_tolist(SocketTArray ta,
+extern void esock_tarray_tolist(SocketTArray ta,
ErlNifEnv* env,
ERL_NIF_TERM* list);
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 5998ff35a4..50cc94c263 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -40,7 +40,7 @@
* should use the compile debug flag, whatever that is...
*/
-// #define COMPILE_DEBUG_FLAG_WE_NEED_TO_CHECK 1
+#define COMPILE_DEBUG_FLAG_WE_NEED_TO_CHECK 1
#if defined(COMPILE_DEBUG_FLAG_WE_NEED_TO_CHECK)
#define UTIL_DEBUG TRUE
#else
@@ -85,53 +85,76 @@ extern
char* esock_encode_msghdr(ErlNifEnv* env,
int read,
struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
ErlNifBinary* ctrlBufP,
ERL_NIF_TERM* eSockAddr)
{
char* xres;
ERL_NIF_TERM addr, iov, ctrl, flags;
+ UDBG( ("SUTIL", "esock_encode_msghdr -> entry with"
+ "\r\n read: %d"
+ "\r\n", read) );
+
if ((xres = esock_encode_sockaddr(env,
(SocketAddress*) msgHdrP->msg_name,
msgHdrP->msg_namelen,
&addr)) != NULL)
return xres;
+ UDBG( ("SUTIL", "esock_encode_msghdr -> try encode iov\r\n") );
if ((xres = esock_encode_iov(env,
read,
msgHdrP->msg_iov,
msgHdrP->msg_iovlen,
+ dataBufP,
&iov)) != NULL)
return xres;
+ UDBG( ("SUTIL", "esock_encode_msghdr -> try encode cmsghdrs\r\n") );
if ((xres = esock_encode_cmsghdrs(env,
ctrlBufP,
msgHdrP,
&ctrl)) != NULL)
return xres;
+ UDBG( ("SUTIL", "esock_encode_msghdr -> try encode flags\r\n") );
if ((xres = esock_encode_mshghdr_flags(env,
msgHdrP->msg_flags,
&flags)) != NULL)
return xres;
+ UDBG( ("SUTIL", "esock_encode_msghdr -> components encoded:"
+ "\r\n addr: %T"
+ "\r\n iov: %T"
+ "\r\n ctrl: %T"
+ "\r\n flags: %T"
+ "\r\n", addr, iov, ctrl, flags) );
{
- ERL_NIF_TERM keys[] = {esock_atom_addr,
- esock_atom_iov,
- esock_atom_ctrl,
- esock_atom_flags};
- ERL_NIF_TERM vals[] = {addr, iov, ctrl, flags};
-
+ ERL_NIF_TERM keys[] = {esock_atom_addr,
+ esock_atom_iov,
+ esock_atom_ctrl,
+ esock_atom_flags};
+ ERL_NIF_TERM vals[] = {addr, iov, ctrl, flags};
unsigned int numKeys = sizeof(keys) / sizeof(ERL_NIF_TERM);
unsigned int numVals = sizeof(vals) / sizeof(ERL_NIF_TERM);
+ ERL_NIF_TERM tmp;
ESOCK_ASSERT( (numKeys == numVals) );
- if (!MKMA(env, keys, vals, numKeys, eSockAddr))
+ UDBG( ("SUTIL", "esock_encode_msghdr -> create msghdr map\r\n") );
+ if (!MKMA(env, keys, vals, numKeys, &tmp))
return ESOCK_STR_EINVAL;
+ UDBG( ("SUTIL", "esock_encode_msghdr -> msghdr: "
+ "\r\n %T"
+ "\r\n", tmp) );
+
+ *eSockAddr = tmp;
}
+ UDBG( ("SUTIL", "esock_encode_msghdr -> done\r\n") );
+
return NULL;
}
@@ -153,6 +176,7 @@ char* esock_encode_iov(ErlNifEnv* env,
int read,
struct iovec* iov,
size_t len,
+ ErlNifBinary* data,
ERL_NIF_TERM* eIOV)
{
int rem = read;
@@ -160,28 +184,51 @@ char* esock_encode_iov(ErlNifEnv* env,
BOOLEAN_T done = FALSE;
ERL_NIF_TERM a[len]; // At most this length
+ UDBG( ("SUTIL", "esock_encode_iov -> entry with"
+ "\r\n read: %d"
+ "\r\n (IOV) len: %d"
+ "\r\n", read, len) );
+
if (len == 0) {
*eIOV = MKEL(env);
return NULL;
}
for (i = 0; (!done) && (i < len); i++) {
+ UDBG( ("SUTIL", "esock_encode_iov -> process iov:"
+ "\r\n iov[%d].iov_len: %d"
+ "\r\n rem: %d"
+ "\r\n", i, iov[i].iov_len, rem) );
if (iov[i].iov_len == rem) {
/* We have the exact amount - we are done */
- a[i] = MKBIN(env, iov[i].iov_base);
+ UDBG( ("SUTIL", "esock_encode_iov -> exact => done\r\n") );
+ a[i] = MKBIN(env, &data[i]);
+ UDBG( ("SUTIL", "esock_encode_iov -> a[%d]: %T\r\n", i, a[i]) );
+ rem = 0; // Besserwisser
done = TRUE;
} else if (iov[i].iov_len < rem) {
/* Filled another buffer - continue */
- a[i] = MKBIN(env, iov[i].iov_base);
+ UDBG( ("SUTIL", "esock_encode_iov -> filled => continue\r\n") );
+ a[i] = MKBIN(env, &data[i]);
+ rem -= iov[i].iov_len;
+ UDBG( ("SUTIL", "esock_encode_iov -> a[%d]: %T\r\n", i, a[i]) );
} else if (iov[i].iov_len > rem) {
/* Partly filled buffer (=> split) - we are done */
- a[i] = MKBIN(env, iov[i].iov_base);
- a[i] = MKSBIN(env, a[i], 0, rem);
+ ERL_NIF_TERM tmp;
+ UDBG( ("SUTIL", "esock_encode_iov -> split => done\r\n") );
+ tmp = MKBIN(env, &data[i]);
+ a[i] = MKSBIN(env, tmp, 0, rem);
+ UDBG( ("SUTIL", "esock_encode_iov -> a[%d]: %T\r\n", i, a[i]) );
+ rem = 0; // Besserwisser
done = TRUE;
}
}
- *eIOV = MKLA(env, a, i+1);
+ UDBG( ("SUTIL", "esock_encode_iov -> create the IOV list (%d)\r\n", i) );
+
+ *eIOV = MKLA(env, a, i);
+
+ UDBG( ("SUTIL", "esock_encode_msghdr -> done\r\n") );
return NULL;
}
@@ -201,11 +248,11 @@ char* esock_encode_iov(ErlNifEnv* env,
* term (which can then in turn be turned into sub-binaries).
*
* We need the cmsgBufP (even though cmsgHdrP points to it) to be able
- * to create sub-binaries (one for each HDR).
+ * to create sub-binaries (one for each cmsg hdr).
*
- * The TArray is created with the size of 128, which should be enough.
- * But if its not, then it will be automatically realloc'ed during add.
- * Once we are done adding hdr's to it, we convert it to a list.
+ * The TArray (term array) is created with the size of 128, which should
+ * be enough. But if its not, then it will be automatically realloc'ed during
+ * add. Once we are done adding hdr's to it, we convert the tarray to a list.
*/
extern
@@ -219,10 +266,16 @@ char* esock_encode_cmsghdrs(ErlNifEnv* env,
struct cmsghdr* firstP = CMSG_FIRSTHDR(msgHdrP);
struct cmsghdr* currentP;
+ UDBG( ("SUTIL", "esock_encode_cmsghdrs -> entry\r\n") );
+
for (currentP = firstP;
currentP != NULL;
currentP = CMSG_NXTHDR(msgHdrP, currentP)) {
+ UDBG( ("SUTIL", "esock_encode_cmsghdrs -> process cmsg header when"
+ "\r\n TArray Size: %d"
+ "\r\n", TARRAY_SZ(cmsghdrs)) );
+
/* MUST check this since on Linux the returned "cmsg" may actually
* go too far!
*/
@@ -248,6 +301,11 @@ char* esock_encode_cmsghdrs(ErlNifEnv* env,
if (esock_encode_protocol(env, currentP->cmsg_level, &level) != NULL)
level = MKI(env, currentP->cmsg_level);
+ UDBG( ("SUTIL", "esock_encode_cmsghdrs -> "
+ "\r\n level: %T"
+ "\r\n type: %T"
+ "\r\n", level, type) );
+
/* And finally create the 'cmsghdr' map -
* and if successfull add it to the tarray.
*/
@@ -274,6 +332,10 @@ char* esock_encode_cmsghdrs(ErlNifEnv* env,
}
}
+ UDBG( ("SUTIL", "esock_encode_cmsghdrs -> cmsg headers processed when"
+ "\r\n TArray Size: %d"
+ "\r\n", TARRAY_SZ(cmsghdrs)) );
+
/* The tarray is populated - convert it to a list */
TARRAY_TOLIST(cmsghdrs, env, eCMsgHdr);
@@ -294,6 +356,10 @@ char* esock_encode_mshghdr_flags(ErlNifEnv* env,
int msgFlags,
ERL_NIF_TERM* flags)
{
+ UDBG( ("SUTIL", "esock_encode_cmsghdrs -> entry with"
+ "\r\n msgFlags: %d (0x%lX)"
+ "\r\n", msgFlags, msgFlags) );
+
if (msgFlags == 0) {
*flags = MKEL(env);
return NULL;
@@ -315,6 +381,10 @@ char* esock_encode_mshghdr_flags(ErlNifEnv* env,
if ((msgFlags & MSG_ERRQUEUE) == MSG_ERRQUEUE)
TARRAY_ADD(ta, esock_atom_errqueue);
+ UDBG( ("SUTIL", "esock_encode_cmsghdrs -> flags processed when"
+ "\r\n TArray size: %d"
+ "\r\n", TARRAY_SZ(ta)) );
+
TARRAY_TOLIST(ta, env, flags);
return NULL;
diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h
index af0bf70d8f..5a79eb3d09 100644
--- a/erts/emulator/nifs/common/socket_util.h
+++ b/erts/emulator/nifs/common/socket_util.h
@@ -39,6 +39,7 @@ extern
char* esock_encode_msghdr(ErlNifEnv* env,
int read,
struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
ErlNifBinary* ctrlBufP,
ERL_NIF_TERM* eSockAddr);
extern
@@ -46,6 +47,7 @@ char* esock_encode_iov(ErlNifEnv* env,
int read,
struct iovec* iov,
size_t len,
+ ErlNifBinary* data,
ERL_NIF_TERM* eIOV);
extern
char* esock_encode_cmsghdrs(ErlNifEnv* env,
diff --git a/lib/kernel/test/socket_server.erl b/lib/kernel/test/socket_server.erl
index 88b63ecf2d..5d00f78b2a 100644
--- a/lib/kernel/test/socket_server.erl
+++ b/lib/kernel/test/socket_server.erl
@@ -33,7 +33,7 @@
-record(manager, {socket, peek, acceptors, handler_id, handlers}).
-record(acceptor, {id, socket, manager}).
--record(handler, {socket, peek, type, manager}).
+-record(handler, {socket, peek, msg, type, manager}).
-define(NUM_ACCEPTORS, 5).
@@ -179,7 +179,7 @@ do_manager_init(Domain, dgram = Type, Proto, Peek) ->
{ok, Name} -> f("~p", [Name]);
{error, R} -> f("error: ~p", [R])
end]),
- case handler_start(1, Sock, Peek) of
+ case handler_start(1, true, Sock, Peek) of
{ok, {Pid, MRef}} ->
i("handler (~p) started", [Pid]),
handler_continue(Pid),
@@ -405,7 +405,7 @@ manager_handle_request(#manager{peek = Peek,
handlers = Handlers} = M, Pid, Ref,
{start_handler, Sock}) ->
i("try start handler (~w)", [HID]),
- case handler_start(HID, Sock, Peek) of
+ case handler_start(HID, false, Sock, Peek) of
{ok, {HPid, HMRef}} ->
i("handler ~w started", [HID]),
manager_reply(Pid, Ref, {ok, HPid}),
@@ -564,10 +564,10 @@ acceptor_handle_accept_success(#acceptor{manager = Manager}, Sock) ->
%% =========================================================================
-handler_start(ID, Sock, Peek) ->
+handler_start(ID, Msg, Sock, Peek) ->
Self = self(),
H = {Pid, _} = spawn_monitor(fun() ->
- handler_init(Self, ID, Peek, Sock)
+ handler_init(Self, ID, Msg, Peek, Sock)
end),
receive
{handler, Pid, ok} ->
@@ -591,7 +591,7 @@ handler_reply(Pid, Ref, Reply) ->
?LIB:reply(handler, Pid, Ref, Reply).
-handler_init(Manager, ID, Peek, Sock) ->
+handler_init(Manager, ID, Msg, Peek, Sock) ->
put(sname, f("handler:~w", [ID])),
i("starting"),
Manager ! {handler, self(), ok},
@@ -720,20 +720,26 @@ handler_init(Manager, ID, Peek, Sock) ->
RtHdr, AuthHdr, HopLimit, HopOpts, DstOpts, FlowInfo,
UHops]),
- handler_loop(#handler{peek = Peek,
+ ok = soip(Sock, pktinfo, true),
+ ok = soip(Sock, recvtos, true),
+ ok = soip(Sock, recvttl, true),
+ %% ok = soip(Sock, recvopts, true),
+
+ handler_loop(#handler{msg = Msg,
+ peek = Peek,
manager = Manager,
type = Type,
socket = Sock})
end.
-%% so(Sock, Lvl, Opt, Val) ->
-%% ok = socket:setopt(Sock, Lvl, Opt, Val).
+so(Sock, Lvl, Opt, Val) ->
+ ok = socket:setopt(Sock, Lvl, Opt, Val).
%% soso(Sock, Opt, Val) ->
%% so(Sock, socket, Opt, Val).
-%% soip(Sock, Opt, Val) ->
-%% so(Sock, ip, Opt, Val).
+soip(Sock, Opt, Val) ->
+ so(Sock, ip, Opt, Val).
%% soipv6(Sock, Opt, Val) ->
%% so(Sock, ipv6, Opt, Val).
@@ -779,6 +785,23 @@ recv(#handler{peek = true, socket = Sock, type = stream}) ->
peek_recv(Sock);
recv(#handler{peek = false, socket = Sock, type = stream}) ->
do_recv(Sock);
+recv(#handler{socket = Sock, msg = true, type = dgram}) ->
+ ok = socket:setopt(Sock, otp, debug, true),
+ case socket:recvmsg(Sock) of
+ {ok, #{addr := Source,
+ iov := [Data],
+ ctrl := CMsgHdrs,
+ flags := Flags}} ->
+ ok = socket:setopt(Sock, otp, debug, false),
+ i("received message: "
+ "~n CMsgHdrs: ~p"
+ "~n Flags: ~p", [CMsgHdrs, Flags]),
+ {ok, {Source, Data}};
+ {ok, X} ->
+ {error, {unexpected, X}};
+ {error, _} = ERROR ->
+ ERROR
+ end;
recv(#handler{peek = Peek, socket = Sock, type = dgram})
when (Peek =:= true) ->
%% ok = socket:setopt(Sock, otp, debug, true),