diff options
author | Micael Karlberg <[email protected]> | 2018-07-31 12:53:52 +0200 |
---|---|---|
committer | Micael Karlberg <[email protected]> | 2018-09-18 14:50:18 +0200 |
commit | d4c6b555aea77198d662822c7f5a134a16cff8af (patch) | |
tree | 51fbbc59bd11e850f866b95f41cccaebdc3f186c | |
parent | 165666d8b8b1b21ffaf43ac436cfc1657ba83649 (diff) | |
download | otp-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.c | 44 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_tarray.c | 8 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_tarray.h | 2 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_util.c | 104 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_util.h | 2 | ||||
-rw-r--r-- | lib/kernel/test/socket_server.erl | 45 |
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), |