aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/nifs/common/socket_nif.c
diff options
context:
space:
mode:
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;
}