diff options
Diffstat (limited to 'erts/emulator/nifs')
-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 |
5 files changed, 125 insertions, 35 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, |