aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/nifs/common/socket_nif.c
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2019-03-11 20:11:16 +0100
committerMicael Karlberg <[email protected]>2019-04-17 16:56:33 +0200
commit143b23ea12795a149f655c644fe519e8ccaa4183 (patch)
tree6d2a925c437e2b9113217c770ba347b2102d7991 /erts/emulator/nifs/common/socket_nif.c
parent228aa89b027b994feaf07a5d4ee83e0e8d6b7796 (diff)
downloadotp-143b23ea12795a149f655c644fe519e8ccaa4183.tar.gz
otp-143b23ea12795a149f655c644fe519e8ccaa4183.tar.bz2
otp-143b23ea12795a149f655c644fe519e8ccaa4183.zip
[socket] Restructure the recvmsg result check
To increase readability the recvmsg result check has been slightly restructured. In this case we made use of the error case function (fail) of the recv result check.
Diffstat (limited to 'erts/emulator/nifs/common/socket_nif.c')
-rw-r--r--erts/emulator/nifs/common/socket_nif.c367
1 files changed, 168 insertions, 199 deletions
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index 1b8f60cdd0..20aa17c3f4 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -2124,7 +2124,8 @@ static ERL_NIF_TERM recv_check_full_done(ErlNifEnv* env,
static ERL_NIF_TERM recv_check_fail(ErlNifEnv* env,
SocketDescriptor* descP,
int saveErrno,
- ErlNifBinary* bufP,
+ ErlNifBinary* buf1P,
+ ErlNifBinary* buf2P,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM recvRef);
static ERL_NIF_TERM recv_check_fail_closed(ErlNifEnv* env,
@@ -2173,6 +2174,13 @@ static ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
ErlNifBinary* ctrlBufP,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM recvRef);
+static ERL_NIF_TERM recvmsg_check_msg(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ int read,
+ struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
+ ErlNifBinary* ctrlBufP,
+ ERL_NIF_TERM sockRef);
static ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env,
SocketDescriptor* descP);
@@ -14213,7 +14221,7 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env,
/* +++ Error handling +++ */
- res = recv_check_fail(env, descP, saveErrno, bufP,
+ res = recv_check_fail(env, descP, saveErrno, bufP, NULL,
sockRef, recvRef);
} else {
@@ -14401,13 +14409,14 @@ static
ERL_NIF_TERM recv_check_fail(ErlNifEnv* env,
SocketDescriptor* descP,
int saveErrno,
- ErlNifBinary* bufP,
+ ErlNifBinary* buf1P,
+ ErlNifBinary* buf2P,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM recvRef)
{
ERL_NIF_TERM res;
- FREE_BIN(bufP);
+ FREE_BIN(buf1P); if (buf2P != NULL) FREE_BIN(buf2P);
if (saveErrno == ECONNRESET) {
@@ -14437,6 +14446,104 @@ ERL_NIF_TERM recv_check_fail(ErlNifEnv* env,
+/* *** recv_check_fail_closed ***
+ *
+ * We detected that the socket was closed wile reading.
+ * Inform current and waiting readers.
+ */
+static
+ERL_NIF_TERM recv_check_fail_closed(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef)
+{
+ ERL_NIF_TERM res = esock_make_error(env, atom_closed);
+ int sres;
+
+ /* <KOLLA>
+ *
+ * IF THE CURRENT PROCESS IS *NOT* THE CONTROLLING
+ * PROCESS, WE NEED TO INFORM IT!!!
+ *
+ * ALL WAITING PROCESSES MUST ALSO GET THE ERROR!!
+ * HANDLED BY THE STOP (CALLBACK) FUNCTION?
+ *
+ * SINCE THIS IS A REMOTE CLOSE, WE DON'T NEED TO WAIT
+ * FOR OUTPUT TO BE WRITTEN (NO ONE WILL READ), JUST
+ * ABORT THE SOCKET REGARDLESS OF LINGER???
+ *
+ * </KOLLA>
+ */
+
+ descP->closeLocal = FALSE;
+ descP->state = SOCKET_STATE_CLOSING;
+
+ recv_error_current_reader(env, descP, sockRef, res);
+
+ if ((sres = esock_select_stop(env, descP->sock, descP)) < 0) {
+ esock_warning_msg("Failed stop select (closed) "
+ "for current reader (%T): %d\r\n",
+ recvRef, sres);
+ }
+
+ return res;
+}
+
+
+
+/* *** recv_check_retry ***
+ *
+ * The recv call would have blocked, so retry.
+ */
+static
+ERL_NIF_TERM recv_check_retry(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM recvRef)
+{
+ int sres;
+ char* xres;
+ ERL_NIF_TERM res;
+
+ descP->rNumCnt = 0;
+ if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL)
+ return esock_make_error_str(env, xres);
+
+ SSDBG( descP, ("SOCKET", "recv_check_retry -> SELECT for more\r\n") );
+
+ if ((sres = esock_select_read(env, descP->sock, descP,
+ NULL, recvRef)) < 0) {
+ res = esock_make_error(env,
+ MKT2(env,
+ esock_atom_select_failed, MKI(env, sres)));
+ } else {
+ res = esock_make_error(env, esock_atom_eagain);
+ }
+
+ return res;
+
+}
+
+
+
+/* *** recv_check_fail_gen ***
+ *
+ * The recv call had a "general" failure.
+ */
+static
+ERL_NIF_TERM recv_check_fail_gen(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ int saveErrno,
+ ERL_NIF_TERM sockRef)
+{
+ ERL_NIF_TERM res = esock_make_error_errno(env, saveErrno);
+
+ recv_error_current_reader(env, descP, sockRef, res);
+
+ return res;
+}
+
+
+
/* *** recv_check_partial ***
*
* Handle a sucessful recv which only partly filled the specified buffer.
@@ -14562,104 +14669,6 @@ ERL_NIF_TERM recv_check_partial_part(ErlNifEnv* env,
-/* *** recv_check_fail_closed ***
- *
- * We detected that the socket was closed wile reading.
- * Inform current and waiting readers.
- */
-static
-ERL_NIF_TERM recv_check_fail_closed(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef)
-{
- ERL_NIF_TERM res = esock_make_error(env, atom_closed);
- int sres;
-
- /* <KOLLA>
- *
- * IF THE CURRENT PROCESS IS *NOT* THE CONTROLLING
- * PROCESS, WE NEED TO INFORM IT!!!
- *
- * ALL WAITING PROCESSES MUST ALSO GET THE ERROR!!
- * HANDLED BY THE STOP (CALLBACK) FUNCTION?
- *
- * SINCE THIS IS A REMOTE CLOSE, WE DON'T NEED TO WAIT
- * FOR OUTPUT TO BE WRITTEN (NO ONE WILL READ), JUST
- * ABORT THE SOCKET REGARDLESS OF LINGER???
- *
- * </KOLLA>
- */
-
- descP->closeLocal = FALSE;
- descP->state = SOCKET_STATE_CLOSING;
-
- recv_error_current_reader(env, descP, sockRef, res);
-
- if ((sres = esock_select_stop(env, descP->sock, descP)) < 0) {
- esock_warning_msg("Failed stop select (closed) "
- "for current reader (%T): %d\r\n",
- recvRef, sres);
- }
-
- return res;
-}
-
-
-
-/* *** recv_check_retry ***
- *
- * The recv call would have blocked, so retry.
- */
-static
-ERL_NIF_TERM recv_check_retry(ErlNifEnv* env,
- SocketDescriptor* descP,
- ERL_NIF_TERM recvRef)
-{
- int sres;
- char* xres;
- ERL_NIF_TERM res;
-
- descP->rNumCnt = 0;
- if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL)
- return esock_make_error_str(env, xres);
-
- SSDBG( descP, ("SOCKET", "recv_check_retry -> SELECT for more\r\n") );
-
- if ((sres = esock_select_read(env, descP->sock, descP,
- NULL, recvRef)) < 0) {
- res = esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed, MKI(env, sres)));
- } else {
- res = esock_make_error(env, esock_atom_eagain);
- }
-
- return res;
-
-}
-
-
-
-/* *** recv_check_fail_gen ***
- *
- * The recv call had a "general" failure.
- */
-static
-ERL_NIF_TERM recv_check_fail_gen(ErlNifEnv* env,
- SocketDescriptor* descP,
- int saveErrno,
- ERL_NIF_TERM sockRef)
-{
- ERL_NIF_TERM res = esock_make_error_errno(env, saveErrno);
-
- recv_error_current_reader(env, descP, sockRef, res);
-
- return res;
-}
-
-
-
/* The recvfrom function delivers one (1) message. If our buffer
* is to small, the message will be truncated. So, regardless
@@ -14690,7 +14699,7 @@ ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
/* +++ Error handling +++ */
- res = recv_check_fail(env, descP, saveErrno, bufP,
+ res = recv_check_fail(env, descP, saveErrno, bufP, NULL,
sockRef, recvRef);
} else {
@@ -14731,7 +14740,9 @@ ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
-/* The recvmsg function delivers one (1) message. If our buffer
+/* *** recvmsg_check_result ***
+ *
+ * The recvmsg function delivers one (1) message. If our buffer
* is to small, the message will be truncated. So, regardless
* if we filled the buffer or not, we have got what we are going
* to get regarding this message.
@@ -14747,7 +14758,6 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM recvRef)
{
- int sres;
ERL_NIF_TERM res;
SSDBG( descP,
@@ -14769,8 +14779,8 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
if ((read == 0) && (descP->type == SOCK_STREAM)) {
/*
- * When a stream socket peer has performed an orderly shutdown, the return
- * value will be 0 (the traditional "end-of-file" return).
+ * When a stream socket peer has performed an orderly shutdown,
+ * the return value will be 0 (the traditional "end-of-file" return).
*
* *We* do never actually try to read 0 bytes from a stream socket!
*/
@@ -14792,119 +14802,78 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
/* +++ Error handling +++ */
- if (saveErrno == ECONNRESET) {
-
- /* +++ Oups - closed +++ */
-
- SSDBG( descP, ("SOCKET", "recvmsg_check_result -> closed\r\n") );
+ res = recv_check_fail(env, descP, saveErrno, dataBufP, ctrlBufP,
+ sockRef, recvRef);
- /* <KOLLA>
- * IF THE CURRENT PROCESS IS *NOT* THE CONTROLLING
- * PROCESS, WE NEED TO INFORM IT!!!
- *
- * ALL WAITING PROCESSES MUST ALSO GET THE ERROR!!
- *
- * </KOLLA>
- */
+ } else {
- res = esock_make_error(env, atom_closed);
- descP->closeLocal = FALSE;
- descP->state = SOCKET_STATE_CLOSING;
+ /* +++ We sucessfully got a message - time to encode it +++ */
- recv_error_current_reader(env, descP, sockRef, res);
+ res = recvmsg_check_msg(env, descP, read, msgHdrP,
+ dataBufP, ctrlBufP, sockRef);
- if ((sres = esock_select_stop(env, descP->sock, descP)) < 0) {
- esock_warning_msg("Failed stop select (closed) "
- "for current reader (%T): %d\r\n",
- recvRef, sres);
- }
+ }
- FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
+ return res;
- return res;;
+}
- } else if ((saveErrno == ERRNO_BLOCK) ||
- (saveErrno == EAGAIN)) {
- char* xres;
- SSDBG( descP, ("SOCKET", "recvmsg_check_result -> eagain\r\n") );
-
- FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
- if ((xres = recv_init_current_reader(env, descP, recvRef)) != NULL)
- return esock_make_error_str(env, xres);
-
- if ((sres = esock_select_read(env, descP->sock, descP,
- NULL, recvRef)) < 0) {
- res = esock_make_error(env,
- MKT2(env,
- esock_atom_select_failed,
- MKI(env, sres)));
- } else {
- res = esock_make_error(env, esock_atom_eagain);
- }
+/* *** recvmsg_check_msg ***
+ *
+ * We successfully read one message. Time to process.
+ */
+static
+ERL_NIF_TERM recvmsg_check_msg(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ int read,
+ struct msghdr* msgHdrP,
+ ErlNifBinary* dataBufP,
+ ErlNifBinary* ctrlBufP,
+ ERL_NIF_TERM sockRef)
+{
+ ERL_NIF_TERM res, eMsgHdr;
+ char* xres;
- return res;
+ /*
+ * <KOLLA>
+ *
+ * The return value of recvmsg is the *total* number of bytes
+ * that where successfully read. This data has been put into
+ * the *IO vector*.
+ *
+ * </KOLLA>
+ */
- } else {
+ if ((xres = encode_msghdr(env, descP,
+ read, msgHdrP, dataBufP, ctrlBufP,
+ &eMsgHdr)) != NULL) {
- res = esock_make_error_errno(env, saveErrno);
+ SSDBG( descP,
+ ("SOCKET",
+ "recvmsg_check_result -> "
+ "(msghdr) encode failed: %s\r\n", xres) );
- SSDBG( descP,
- ("SOCKET",
- "recvmsg_check_result -> errno: %d\r\n", saveErrno) );
-
- recv_error_current_reader(env, descP, sockRef, res);
+ recv_update_current_reader(env, descP, sockRef);
- FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
+ FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
- return res;
- }
+ res = esock_make_error_str(env, xres);
} else {
- /* +++ We sucessfully got a message - time to encode it +++ */
-
- ERL_NIF_TERM eMsgHdr;
- char* xres;
-
- /*
- * <KOLLA>
- *
- * The return value of recvmsg is the *total* number of bytes
- * that where successfully read. This data has been put into
- * the *IO vector*.
- *
- * </KOLLA>
- */
-
- if ((xres = encode_msghdr(env, descP,
- read, msgHdrP, dataBufP, ctrlBufP,
- &eMsgHdr)) != NULL) {
-
- SSDBG( descP,
- ("SOCKET",
- "recvmsg_check_result -> "
- "(msghdr) encode failed: %s\r\n", xres) );
-
- recv_update_current_reader(env, descP, sockRef);
-
- FREE_BIN(dataBufP); FREE_BIN(ctrlBufP);
-
- return esock_make_error_str(env, xres);
- } else {
-
- SSDBG( descP,
- ("SOCKET",
- "recvmsg_check_result -> "
- "(msghdr) encode ok: %T\r\n", eMsgHdr) );
-
- recv_update_current_reader(env, descP, sockRef);
+ SSDBG( descP,
+ ("SOCKET",
+ "recvmsg_check_result -> "
+ "(msghdr) encode ok: %T\r\n", eMsgHdr) );
- return esock_make_ok2(env, eMsgHdr);
- }
+ recv_update_current_reader(env, descP, sockRef);
+ res = esock_make_ok2(env, eMsgHdr);
}
+
+ return res;
}