diff options
author | Raimo Niskanen <[email protected]> | 2011-09-15 09:18:29 +0200 |
---|---|---|
committer | Raimo Niskanen <[email protected]> | 2011-11-17 12:11:03 +0100 |
commit | d661742424dfa8ecbc2797845b810383c356b268 (patch) | |
tree | bee4ef9f22e183263ccae8dbb1745a3c77e3936c | |
parent | 6dd80f3e9a556dc94ae59280f532e153e463b798 (diff) | |
download | otp-d661742424dfa8ecbc2797845b810383c356b268.tar.gz otp-d661742424dfa8ecbc2797845b810383c356b268.tar.bz2 otp-d661742424dfa8ecbc2797845b810383c356b268.zip |
erts: Improve SCTP message defragmenting
Receive several fragments within the same receive loop if possible.
-rw-r--r-- | erts/emulator/drivers/common/inet_drv.c | 47 |
1 files changed, 32 insertions, 15 deletions
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 79422dc54c..bab31951a5 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -10093,6 +10093,7 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) struct msghdr mhdr; /* Top-level msg structure */ struct iovec iov[1]; /* Data or Notification Event */ char ancd[SCTP_ANC_BUFF_SIZE]; /* Ancillary Data */ + int short_recv = 0; #endif while(packet_count--) { @@ -10146,21 +10147,18 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) if ((desc->state & INET_F_ACTIVE)) { n = sock_recv(desc->s, udesc->i_ptr, desc->bufsz, 0); other = desc->remote; + goto check_result; } - else { - n = sock_recvfrom(desc->s, udesc->i_ptr, desc->bufsz, - 0, &other.sa, &len); - } - -#ifdef HAVE_SCTP + n = sock_recvfrom(desc->s, udesc->i_ptr, desc->bufsz, + 0, &other.sa, &len); check_result: -#endif /* Analyse the result: */ if (IS_SOCKET_ERROR(n)) { int err = sock_errno(); - release_buffer(udesc->i_buf); - udesc->i_buf = NULL; if (err != ERRNO_BLOCK) { + /* real error */ + release_buffer(udesc->i_buf); + udesc->i_buf = NULL; if (!desc->active) { async_error(desc, err); driver_cancel_timer(desc->port); @@ -10170,21 +10168,30 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) /* This is for an active desc only: */ packet_error_message(udesc, err); } + return count; } - else if (!desc->active) + /* would block error - try again */ + if (!desc->active +#ifdef HAVE_SCTP + || short_recv +#endif + ) { sock_select(desc,FD_READ,1); + } return count; /* strange, not ready */ } + #ifdef HAVE_SCTP - else if (IS_SCTP(desc) && !(mhdr.msg_flags & MSG_EOR)) { - /* short recv */ + if (IS_SCTP(desc) && (short_recv = !(mhdr.msg_flags & MSG_EOR))) { + /* SCTP non-final message fragment */ inet_input_count(desc, n); udesc->i_ptr += n; - sock_select(desc, FD_READ, 1); - return count; /* more fragments will come later */ + continue; /* wait for more fragments */ } #endif - else { + + { + /* message received */ int code; void * extra = NULL; char * ptr; @@ -10233,7 +10240,17 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event) return count; /* passive mode (read one packet only) */ } } + } /* while(packet_count--) { */ + + /* we ran out of tries (packet_count) either on an active socket + * that got that many messages or an SCTP socket that got that + * many message fragments but still not the final + */ +#ifdef HAVE_SCTP + if (short_recv) { + sock_select(desc, FD_READ, 1); } +#endif return count; } |