summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/net_common.c155
1 files changed, 92 insertions, 63 deletions
diff --git a/source/net_common.c b/source/net_common.c
index e81a9b5..17b03b7 100644
--- a/source/net_common.c
+++ b/source/net_common.c
@@ -757,123 +757,152 @@ const char *NET_ErrorString( void ) {
#endif
}
-static qboolean NET_StringToIface( const char *s, struct sockaddr_in *sadr ) {
- if( *s ) {
- return NET_StringToSockaddr( s, sadr );
+static qboolean get_bind_addr( const char *iface, int port, struct sockaddr_in *sadr ) {
+ if( *iface ) {
+ if( !NET_StringToSockaddr( iface, sadr ) ) {
+ return qfalse;
+ }
+ } else {
+ // empty string binds to all interfaces
+ memset( sadr, 0, sizeof( *sadr ) );
+ sadr->sin_family = AF_INET;
+ sadr->sin_addr.s_addr = INADDR_ANY;
+ }
+ if( port != PORT_ANY ) {
+ sadr->sin_port = htons( ( u_short )port );
}
- // empty string binds to all interfaces
- memset( sadr, 0, sizeof( *sadr ) );
- sadr->sin_family = AF_INET;
- sadr->sin_addr.s_addr = INADDR_ANY;
return qtrue;
}
-static SOCKET UDP_OpenSocket( const char *interface, int port ) {
- SOCKET newsocket;
- struct sockaddr_in address;
- u_long _true = 1;
+static SOCKET create_socket( int type, int proto ) {
+ SOCKET ret = socket( PF_INET, type, proto );
- Com_DPrintf( "Opening UDP socket: %s:%i\n", interface, port );
+ NET_GET_ERROR();
+ return ret;
+}
- newsocket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
- if( newsocket == INVALID_SOCKET ) {
- NET_GET_ERROR();
+static int enable_option( SOCKET s, int level, int optname ) {
+ u_long _true = 1;
+ int ret = setsockopt( s, level, optname, ( char * )&_true, sizeof( _true ) );
+
+ NET_GET_ERROR();
+ return ret;
+}
+
+static int make_nonblock( SOCKET s ) {
+ u_long _true = 1;
+ int ret = ioctlsocket( s, FIONBIO, &_true );
+
+ NET_GET_ERROR();
+ return ret;
+}
+
+static int bind_socket( SOCKET s, struct sockaddr_in *sadr ) {
+ int ret = bind( s, ( struct sockaddr * )sadr, sizeof( *sadr ) );
+
+ NET_GET_ERROR();
+ return ret;
+}
+
+static SOCKET UDP_OpenSocket( const char *iface, int port ) {
+ SOCKET s;
+ struct sockaddr_in sadr;
+
+ Com_DPrintf( "Opening UDP socket: %s:%i\n", iface, port );
+
+ s = create_socket( SOCK_DGRAM, IPPROTO_UDP );
+ if( s == INVALID_SOCKET ) {
+ Com_EPrintf( "%s: %s:%d: can't create socket: %s\n",
+ __func__, iface, port, NET_ErrorString() );
return INVALID_SOCKET;
}
// make it non-blocking
- if( ioctlsocket( newsocket, FIONBIO, &_true ) == -1 ) {
+ if( make_nonblock( s ) == -1 ) {
+ Com_EPrintf( "%s: %s:%d: can't make socket non-blocking: %s\n",
+ __func__, iface, port, NET_ErrorString() );
goto fail;
}
// make it broadcast capable
- _true = 1;
- if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST,
- ( char * )&_true, sizeof( _true ) ) == -1 )
- {
- goto fail;
+ if( enable_option( s, SOL_SOCKET, SO_BROADCAST ) == -1 ) {
+ Com_WPrintf( "%s: %s:%d: can't make socket broadcast capable: %s\n",
+ __func__, iface, port, NET_ErrorString() );
}
#ifdef __linux__
// enable ICMP error queue
if( !net_ignore_icmp->integer ) {
- _true = 1;
- if( setsockopt( newsocket, IPPROTO_IP, IP_RECVERR,
- ( char * )&_true, sizeof( _true ) ) == -1 )
- {
- goto fail;
+ if( enable_option( s, IPPROTO_IP, IP_RECVERR ) == -1 ) {
+ Com_WPrintf( "%s: %s:%d: can't enable ICMP error queue: %s\n",
+ __func__, iface, port, NET_ErrorString() );
}
}
#endif
- if( !NET_StringToIface( interface, &address ) ) {
- Com_Printf( "Bad interface address: %s\n", interface );
+ // resolve iface sadr
+ if( !get_bind_addr( iface, port, &sadr ) ) {
+ Com_EPrintf( "%s: %s:%d: bad interface address\n",
+ __func__, iface, port );
goto fail;
}
- if( port != PORT_ANY ) {
- address.sin_port = htons( ( u_short )port );
+ if( bind_socket( s, &sadr ) == -1 ) {
+ Com_EPrintf( "%s: %s:%d: can't bind socket: %s\n",
+ __func__, iface, port, NET_ErrorString() );
+ goto fail;
}
- if( !bind( newsocket, ( struct sockaddr * )&address, sizeof( address ) ) ) {
- return newsocket;
- }
+ return s;
fail:
- NET_GET_ERROR();
- closesocket( newsocket );
- Com_EPrintf( "%s: %s:%d: %s\n", __func__,
- interface, port, NET_ErrorString() );
+ closesocket( s );
return INVALID_SOCKET;
}
-static SOCKET TCP_OpenSocket( const char *interface, int port, netsrc_t who ) {
- SOCKET newsocket;
- struct sockaddr_in address;
- u_long _true;
+static SOCKET TCP_OpenSocket( const char *iface, int port, netsrc_t who ) {
+ SOCKET s;
+ struct sockaddr_in sadr;
- Com_DPrintf( "Opening TCP socket: %s:%i\n", interface, port );
+ Com_DPrintf( "Opening TCP socket: %s:%i\n", iface, port );
- newsocket = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
- if( newsocket == INVALID_SOCKET ) {
- NET_GET_ERROR();
+ s = create_socket( SOCK_STREAM, IPPROTO_TCP );
+ if( s == INVALID_SOCKET ) {
+ Com_EPrintf( "%s: %s:%d: can't create socket: %s\n",
+ __func__, iface, port, NET_ErrorString() );
return INVALID_SOCKET;
}
// make it non-blocking
- _true = 1;
- if( ioctlsocket( newsocket, FIONBIO, &_true ) == -1 ) {
+ if( make_nonblock( s ) == -1 ) {
+ Com_EPrintf( "%s: %s:%d: can't make socket non-blocking: %s\n",
+ __func__, iface, port, NET_ErrorString() );
goto fail;
}
// give it a chance to reuse previous port
if( who == NS_SERVER ) {
- _true = 1;
- if( setsockopt( newsocket, SOL_SOCKET, SO_REUSEADDR,
- ( char * )&_true, sizeof( _true ) ) == -1 )
- {
- goto fail;
+ if( enable_option( s, SOL_SOCKET, SO_REUSEADDR ) == -1 ) {
+ Com_WPrintf( "%s: %s:%d: can't force socket to reuse address: %s\n",
+ __func__, iface, port, NET_ErrorString() );
}
}
- if( !NET_StringToIface( interface, &address ) ) {
- Com_Printf( "Bad interface address: %s\n", interface );
+ if( !get_bind_addr( iface, port, &sadr ) ) {
+ Com_EPrintf( "%s: %s:%d: bad interface address\n",
+ __func__, iface, port );
goto fail;
}
- if( port != PORT_ANY ) {
- address.sin_port = htons( ( u_short )port );
- }
- if( !bind( newsocket, ( struct sockaddr * )&address, sizeof( address ) ) ) {
- return newsocket;
+ if( bind_socket( s, &sadr ) == -1 ) {
+ Com_EPrintf( "%s: %s:%d: can't bind socket: %s\n",
+ __func__, iface, port, NET_ErrorString() );
+ goto fail;
}
fail:
- NET_GET_ERROR();
- closesocket( newsocket );
- Com_EPrintf( "%s: %s:%d: %s\n", __func__,
- interface, port, NET_ErrorString() );
+ closesocket( s );
return INVALID_SOCKET;
}