summaryrefslogtreecommitdiff
path: root/source/net_common.c
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2009-10-19 17:03:12 +0000
committerAndrey Nazarov <skuller@skuller.net>2009-10-19 17:03:12 +0000
commit67741c8e568f256340e132cb3d888365d2f89b4e (patch)
treef0e7476606240d15d48034d16d61866ed08cface /source/net_common.c
parent0e0550d845cc81041fd992bd677a3f5fe4ec616e (diff)
Always suck ICMP error queue on Linux once recvfrom/sento returned an error, don't attempt to be smart about error types.
Diffstat (limited to 'source/net_common.c')
-rw-r--r--source/net_common.c58
1 files changed, 23 insertions, 35 deletions
diff --git a/source/net_common.c b/source/net_common.c
index 472d772..2173ff4 100644
--- a/source/net_common.c
+++ b/source/net_common.c
@@ -485,13 +485,16 @@ static void icmp_error_event( netsrc_t sock ) {
// Linux at least supports receiving ICMP errors on unconnected UDP sockets
// via IP_RECVERR cruft below... What about BSD?
-static void process_error_queue( netsrc_t sock ) {
+static int process_error_queue( netsrc_t sock ) {
byte buffer[1024];
struct sockaddr_in from;
struct msghdr msg;
struct cmsghdr *cmsg;
struct sock_extended_err *ee;
//struct sockaddr_in *off;
+ int tries;
+
+ tries = 0;
retry:
memset( &from, 0, sizeof( from ) );
@@ -512,12 +515,12 @@ retry:
default:
Com_EPrintf( "%s: %s\n", __func__, NET_ErrorString() );
}
- return;
+ return tries;
}
if( !( msg.msg_flags & MSG_ERRQUEUE ) ) {
Com_DPrintf( "%s: no extended error received\n", __func__ );
- return;
+ return tries;
}
// find an ICMP error message
@@ -539,7 +542,7 @@ retry:
if( !cmsg ) {
Com_DPrintf( "%s: no ICMP error found\n", __func__ );
- return;
+ return tries;
}
/*
@@ -550,20 +553,15 @@ retry:
NET_SockadrToNetadr( &from, &net_from );
- // handle most common ICMP errors (defined in linux/net/ipv4/icmp.c)
+ // handle ICMP errors
net_error = ee->ee_errno;
- switch( net_error ) {
- case ENETUNREACH:
- case EHOSTUNREACH:
- case EHOSTDOWN:
- case ECONNREFUSED:
- case ENONET:
- icmp_error_event( sock );
+ icmp_error_event( sock );
+
+ if( ++tries < MAX_ERROR_RETRIES ) {
goto retry;
- default:
- Com_EPrintf( "%s: %s from %s\n", __func__,
- NET_ErrorString(), NET_AdrToString( &net_from ) );
}
+
+ return tries;
}
#endif // __linux__
@@ -639,21 +637,16 @@ retry:
case EWOULDBLOCK:
// wouldblock is silent
break;
+ default:
#if USE_ICMP
- case ENETUNREACH:
- case EHOSTUNREACH:
- case EHOSTDOWN:
- case ECONNREFUSED:
- case ENONET:
// recvfrom() fails on Linux if there's an ICMP originated
// pending error on socket. suck up error queue and retry...
- process_error_queue( sock );
- if( ++tries < MAX_ERROR_RETRIES ) {
- goto retry;
+ if( process_error_queue( sock ) ) {
+ if( ++tries < MAX_ERROR_RETRIES ) {
+ goto retry;
+ }
}
- // intentional fallthrough
#endif
- default:
Com_DPrintf( "%s: %s from %s\n", __func__,
NET_ErrorString(), NET_AdrToString( &net_from ) );
net_recv_errors++;
@@ -787,21 +780,16 @@ retry:
case EWOULDBLOCK:
// wouldblock is silent
break;
+ default:
#if USE_ICMP
- case ENETUNREACH:
- case EHOSTUNREACH:
- case EHOSTDOWN:
- case ECONNREFUSED:
- case ENONET:
// sendto() fails on Linux if there's an ICMP originated
// pending error on socket. suck up error queue and retry...
- process_error_queue( sock );
- if( ++tries < MAX_ERROR_RETRIES ) {
- goto retry;
+ if( process_error_queue( sock ) ) {
+ if( ++tries < MAX_ERROR_RETRIES ) {
+ goto retry;
+ }
}
- // intentional fallthrough
#endif
- default:
Com_DPrintf( "%s: %s to %s\n", __func__,
NET_ErrorString(), NET_AdrToString( to ) );
net_send_errors++;