/* ============= Sys_StringToNetAdr ============= */ bool Sys_StringToNetAdr( const char *s, netadr_t *a, bool doDNSResolve ) { struct sockaddr sadr; if ( !Net_StringToSockaddr( s, &sadr, doDNSResolve ) ) { return false; } Net_SockadrToNetadr( &sadr, a ); return true; }
/* ================== Net_GetUDPPacket ================== */ bool Net_GetUDPPacket( int netSocket, netadr_t &net_from, char *data, int &size, int maxSize ) { int ret; struct sockaddr from; int fromlen; int err; if( !netSocket ) { return false; } fromlen = sizeof(from); ret = recvfrom( netSocket, data, maxSize, 0, (struct sockaddr *)&from, &fromlen ); if ( ret == SOCKET_ERROR ) { err = WSAGetLastError(); if( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) { return false; } char buf[1024]; sprintf( buf, "Net_GetUDPPacket: %s\n", NET_ErrorString() ); OutputDebugString( buf ); return false; } if ( netSocket == ip_socket ) { memset( ((struct sockaddr_in *)&from)->sin_zero, 0, 8 ); } if ( usingSocks && netSocket == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) { if ( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 ) { return false; } net_from.type = NA_IP; net_from.ip[0] = data[4]; net_from.ip[1] = data[5]; net_from.ip[2] = data[6]; net_from.ip[3] = data[7]; net_from.port = *(short *)&data[8]; memmove( data, &data[10], ret - 10 ); } else { Net_SockadrToNetadr( &from, &net_from ); } if( ret == maxSize ) { char buf[1024]; sprintf( buf, "Net_GetUDPPacket: oversize packet from %s\n", Sys_NetAdrToString( net_from ) ); OutputDebugString( buf ); return false; } size = ret; return true; }
/* ======================== Net_GetUDPPacket ======================== */ bool Net_GetUDPPacket( int netSocket, netadr_t& net_from, char* data, int& size, int maxSize ) { int ret; sockaddr_in from; socklen_t fromlen; int err; if( !netSocket ) { return false; } fromlen = sizeof( from ); ret = recvfrom( netSocket, data, maxSize, 0, ( sockaddr* )&from, &fromlen ); if( ret == SOCKET_ERROR ) { err = Net_GetLastError(); if( err == D3_NET_EWOULDBLOCK || err == D3_NET_ECONNRESET ) { return false; } idLib::Printf( "Net_GetUDPPacket: %s\n", NET_ErrorString() ); return false; } #if 0 // TODO: WTF was this about? // DG: ip_socket is never initialized, so this is dead code // - and if netSocket is 0 (so this would be true) recvfrom above will already fail if( static_cast<unsigned int>( netSocket ) == ip_socket ) { memset( from.sin_zero, 0, sizeof( from.sin_zero ) ); } if( usingSocks && static_cast<unsigned int>( netSocket ) == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) { if( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 ) { return false; } net_from.type = NA_IP; net_from.ip[0] = data[4]; net_from.ip[1] = data[5]; net_from.ip[2] = data[6]; net_from.ip[3] = data[7]; net_from.port = *( short* )&data[8]; memmove( data, &data[10], ret - 10 ); } else { #endif // 0 Net_SockadrToNetadr( &from, &net_from ); #if 0 // this is ugly, but else astyle is confused } #endif if( ret > maxSize ) { idLib::Printf( "Net_GetUDPPacket: oversize packet from %s\n", Sys_NetAdrToString( net_from ) ); return false; } size = ret; return true; }
/* ======================== NET_IPSocket ======================== */ int NET_IPSocket( const char* bind_ip, int port, netadr_t* bound_to ) { SOCKET newsocket; sockaddr_in address; if( port != PORT_ANY ) { if( bind_ip ) { idLib::Printf( "Opening IP socket: %s:%i\n", bind_ip, port ); } else { idLib::Printf( "Opening IP socket: localhost:%i\n", port ); } } if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) { idLib::Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() ); return 0; } // make it non-blocking #ifdef _WIN32 // which has no fcntl() unsigned long _true = 1; if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) { idLib::Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() ); closesocket( newsocket ); return 0; } #else int flags = fcntl( newsocket, F_GETFL, 0 ); if( flags < 0 ) { idLib::Printf( "WARNING: UDP_OpenSocket: fcntl F_GETFL: %s\n", NET_ErrorString() ); closesocket( newsocket ); return 0; } flags |= O_NONBLOCK; if( fcntl( newsocket, F_SETFL, flags ) < 0 ) { idLib::Printf( "WARNING: UDP_OpenSocket: fcntl F_SETFL with O_NONBLOCK: %s\n", NET_ErrorString() ); closesocket( newsocket ); return 0; } #endif // make it broadcast capable int i = 1; if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, ( char* )&i, sizeof( i ) ) == SOCKET_ERROR ) { idLib::Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() ); closesocket( newsocket ); return 0; } if( !bind_ip || !bind_ip[0] || !idStr::Icmp( bind_ip, "localhost" ) ) { address.sin_addr.s_addr = INADDR_ANY; } else { Net_StringToSockaddr( bind_ip, &address, true ); } if( port == PORT_ANY ) { address.sin_port = 0; } else { address.sin_port = htons( ( short )port ); } address.sin_family = AF_INET; if( bind( newsocket, ( const sockaddr* )&address, sizeof( address ) ) == SOCKET_ERROR ) { idLib::Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() ); closesocket( newsocket ); return 0; } // if the port was PORT_ANY, we need to query again to know the real port we got bound to // ( this used to be in idUDP::InitForPort ) if( bound_to ) { socklen_t len = sizeof( address ); if( getsockname( newsocket, ( struct sockaddr* )&address, &len ) == SOCKET_ERROR ) { common->Printf( "ERROR: IPSocket: getsockname: %s\n", NET_ErrorString() ); closesocket( newsocket ); return 0; } Net_SockadrToNetadr( &address, bound_to ); } return newsocket; }
/* ==================== NET_IPSocket ==================== */ int NET_IPSocket( const char *net_interface, int port, netadr_t *bound_to ) { SOCKET newsocket; struct sockaddr_in address; unsigned long _true = 1; int i = 1; int err; if( net_interface ) { common->DPrintf( "Opening IP socket: %s:%i\n", net_interface, port ); } else { common->DPrintf( "Opening IP socket: localhost:%i\n", port ); } if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) { err = WSAGetLastError(); if( err != WSAEAFNOSUPPORT ) { common->Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() ); } return 0; } // make it non-blocking if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) { common->Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() ); return 0; } // make it broadcast capable if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR ) { common->Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() ); return 0; } if( !net_interface || !net_interface[0] || !idStr::Icmp( net_interface, "localhost" ) ) { address.sin_addr.s_addr = INADDR_ANY; } else { Net_StringToSockaddr( net_interface, (struct sockaddr *)&address, true ); } if( port == PORT_ANY ) { address.sin_port = 0; } else { address.sin_port = htons( (short)port ); } address.sin_family = AF_INET; if( bind( newsocket, (const struct sockaddr *)&address, sizeof(address) ) == SOCKET_ERROR ) { common->Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() ); closesocket( newsocket ); return 0; } // if the port was PORT_ANY, we need to query again to know the real port we got bound to // ( this used to be in idPort::InitForPort ) if ( bound_to ) { int len = sizeof( address ); getsockname( newsocket, (sockaddr *)&address, &len ); Net_SockadrToNetadr( (sockaddr *)&address, bound_to ); } return newsocket; }