X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=net_udp.c;h=353fc7bed32eb6eb5145b6c27ad38bdd23ff52a6;hp=9b91330680991ac0b860b9c99b2afa8ab14e4d01;hb=038ff8d79bb5044145cc2f87a8df1ce732209e4d;hpb=c4ee1bbcc6b2f917465f07269ad09942bbf40849 diff --git a/net_udp.c b/net_udp.c index 9b913306..353fc7be 100644 --- a/net_udp.c +++ b/net_udp.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -17,13 +17,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// net_udp.c - #include "quakedef.h" - +#include "net_udp.h" +#ifdef WIN32 +#include "winquake.h" +#define MAXHOSTNAMELEN 256 +#else +#include #include #include #include +#include #include #include #include @@ -36,55 +40,92 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef NeXT #include #endif - -extern int gethostname (char *, int); -extern int close (int); +#endif static int net_acceptsocket = -1; // socket for fielding new connections static int net_controlsocket; static int net_broadcastsocket = 0; static struct qsockaddr broadcastaddr; -static unsigned long myAddr; - -#include "net_udp.h" +static union {int i;unsigned char d[4];} myAddr; //============================================================================= +#ifdef WIN32 +WSADATA winsockdata; +#endif + int UDP_Init (void) { + int i, j; struct hostent *local; - char buff[MAXHOSTNAMELEN]; - struct qsockaddr addr; - char *colon; - + char buff[MAXHOSTNAMELEN]; + if (COM_CheckParm ("-noudp")) return -1; - // determine my name & address - gethostname(buff, MAXHOSTNAMELEN); - local = gethostbyname(buff); - myAddr = *(int *)local->h_addr_list[0]; - - // if the quake hostname isn't set, set it to the machine name - if (strcmp(hostname.string, "UNNAMED") == 0) +#ifdef WIN32 + if (WSAStartup (MAKEWORD(1, 1), &winsockdata)) { - buff[15] = 0; - Cvar_Set ("hostname", buff); + Con_SafePrintf ("Winsock initialization failed.\n"); + return -1; } +#endif - if ((net_controlsocket = UDP_OpenSocket (0)) == -1) - Sys_Error("UDP_Init: Unable to open control socket\n"); + // loopback as a worst case fallback + myAddr.i = htonl(INADDR_ANY); - ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; - ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST; - ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport); + net_controlsocket = -1; + for (j = 0;net_controlsocket == -1;j++) + { + switch(j) + { + case 0: + if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) + myAddr.i = inet_addr(com_argv[i+1]); + break; + case 1: + myAddr.i = htonl(INADDR_ANY); + break; + case 2: + if (gethostname(buff, MAXHOSTNAMELEN) != -1) + { + buff[MAXHOSTNAMELEN - 1] = 0; + local = gethostbyname(buff); + if (local != NULL) + myAddr.i = *((int *)local->h_addr_list[0]); + else + continue; + } + else + continue; + break; + default: + Con_Printf("UDP_Init: Giving up, UDP networking support disabled.\n"); +#ifdef WIN32 + WSACleanup (); +#endif + return -1; + } - UDP_GetSocketAddr (net_controlsocket, &addr); - strcpy(my_tcpip_address, UDP_AddrToString (&addr)); - colon = strrchr (my_tcpip_address, ':'); - if (colon) - *colon = 0; + if (myAddr.i == htonl(INADDR_LOOPBACK)) + sprintf(my_tcpip_address, "INADDR_LOOPBACK"); + else if (myAddr.i == htonl(INADDR_ANY)) + sprintf(my_tcpip_address, "INADDR_ANY"); + else if (myAddr.i == htonl(INADDR_NONE)) + sprintf(my_tcpip_address, "INADDR_NONE"); + else + sprintf(my_tcpip_address, "%d.%d.%d.%d", myAddr.d[0], myAddr.d[1], myAddr.d[2], myAddr.d[3]); + Con_Printf("UDP_Init: Binding to IP Interface Address of %s... ", my_tcpip_address); + if ((net_controlsocket = UDP_OpenSocket (0)) == -1) + Con_Printf("failed\n"); + else + Con_Printf("succeeded\n"); + } + + ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; + ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = htonl(INADDR_BROADCAST); + ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((unsigned short)net_hostport); Con_Printf("UDP Initialized\n"); tcpipAvailable = true; @@ -98,6 +139,9 @@ void UDP_Shutdown (void) { UDP_Listen (false); UDP_CloseSocket (net_controlsocket); +#ifdef WIN32 + WSACleanup (); +#endif } //============================================================================= @@ -127,94 +171,55 @@ int UDP_OpenSocket (int port) { int newsocket; struct sockaddr_in address; - qboolean _true = true; if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return -1; - if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1) - goto ErrorReturn; + { +#ifdef WIN32 + u_long _true = 1; + if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) + { + closesocket (newsocket); +#else + char _true = 1; + if (ioctl (newsocket, FIONBIO, &_true) == -1) + { + close (newsocket); +#endif + Sys_Error("UDP_OpenSocket: unable to do a ioctl FIONBIO on the socket\n"); + } + } address.sin_family = AF_INET; - address.sin_addr.s_addr = INADDR_ANY; - address.sin_port = htons(port); - if( bind (newsocket, (void *)&address, sizeof(address)) == -1) - goto ErrorReturn; + address.sin_addr.s_addr = myAddr.i; + address.sin_port = htons((unsigned short)port); + if (bind(newsocket, (void *)&address, sizeof(address)) == -1) + { +#ifdef WIN32 + closesocket(newsocket); +#else + close(newsocket); +#endif + Sys_Error ("UDP_OpenSocket: Unable to bind to %s", UDP_AddrToString((struct qsockaddr *)&address)); + } return newsocket; - -ErrorReturn: - close (newsocket); - return -1; } //============================================================================= int UDP_CloseSocket (int socket) { - if (socket == net_broadcastsocket) + if (net_broadcastsocket == socket) net_broadcastsocket = 0; +#ifdef WIN32 + return closesocket (socket); +#else return close (socket); +#endif } - -//============================================================================= -/* -============ -PartialIPAddress - -this lets you type only as much of the net address as required, using -the local network components to fill in the rest -============ -*/ -static int PartialIPAddress (char *in, struct qsockaddr *hostaddr) -{ - char buff[256]; - char *b; - int addr; - int num; - int mask; - int run; - int port; - - buff[0] = '.'; - b = buff; - strcpy(buff+1, in); - if (buff[1] == '.') - b++; - - addr = 0; - mask=-1; - while (*b == '.') - { - b++; - num = 0; - run = 0; - while (!( *b < '0' || *b > '9')) - { - num = num*10 + *b++ - '0'; - if (++run > 3) - return -1; - } - if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) - return -1; - if (num < 0 || num > 255) - return -1; - mask<<=8; - addr = (addr<<8) + num; - } - - if (*b++ == ':') - port = atoi(b); - else - port = net_hostport; - - hostaddr->sa_family = AF_INET; - ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); - ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr); - - return 0; -} //============================================================================= int UDP_Connect (int socket, struct qsockaddr *addr) @@ -226,32 +231,70 @@ int UDP_Connect (int socket, struct qsockaddr *addr) int UDP_CheckNewConnections (void) { + char buf[4096]; +#ifndef WIN32 unsigned long available; struct sockaddr_in from; socklen_t fromlen; - char buff[1]; +#endif if (net_acceptsocket == -1) return -1; +#ifdef WIN32 + if (recvfrom (net_acceptsocket, buf, sizeof(buf), MSG_PEEK, NULL, NULL) >= 0) + return net_acceptsocket; +#else if (ioctl (net_acceptsocket, FIONREAD, &available) == -1) Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n"); if (available) return net_acceptsocket; - recvfrom (net_acceptsocket, buff, 0, 0, (struct sockaddr *) &from, &fromlen); + recvfrom (net_acceptsocket, buf, 0, 0, (struct sockaddr *) &from, &fromlen); +#endif return -1; } //============================================================================= +int UDP_Recv (qbyte *buf, int len, struct qsockaddr *addr) +{ + return UDP_Read (net_acceptsocket, buf, len, addr); +} + +//============================================================================= + +int UDP_Send (qbyte *buf, int len, struct qsockaddr *addr) +{ + return UDP_Write (net_acceptsocket, buf, len, addr); +} + +//============================================================================= + int UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr) { int addrlen = sizeof (struct qsockaddr); int ret; ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen); - if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED)) - return 0; + if (ret == -1) + { +#ifdef WIN32 + int e = WSAGetLastError(); + if (e == WSAEWOULDBLOCK || e == WSAECONNREFUSED) + return 0; + Con_Printf("UDP_Read(%i, %p, %i, <%s>): WSAGetLastError == %i\n", socket, buf, len, UDP_AddrToString(addr), e); +#else + if (errno == EWOULDBLOCK || errno == ECONNREFUSED) + return 0; + Con_Printf("UDP_Read(%i, %p, %i, <%s>): errno == %i (%s)\n", socket, buf, len, UDP_AddrToString(addr), errno, strerror(errno)); +#endif + } + else if (developer_networking.integer) + { + Con_Printf("UDP_Read(%i, %p, %i, <%s>) = %i\n", socket, buf, len, UDP_AddrToString(addr), ret); + Com_HexDumpToConsole(buf, ret); + } + return ret; } @@ -259,7 +302,7 @@ int UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr) int UDP_MakeSocketBroadcastCapable (int socket) { - int i = 1; + int i = 1; // make this socket broadcast capable if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) @@ -296,60 +339,93 @@ int UDP_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr) { int ret; + if (developer_networking.integer) + { + Con_Printf("UDP_Write(%i, %p, %i, <%s>)\n", socket, buf, len, UDP_AddrToString(addr)); + Com_HexDumpToConsole(buf, len); + } + ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); - if (ret == -1 && errno == EWOULDBLOCK) - return 0; + if (ret == -1) + { +#ifdef WIN32 + int e = WSAGetLastError(); + if (e == WSAEWOULDBLOCK) + return 0; + Con_Printf("UDP_Write(%i, %p, %i, <%s>): WSAGetLastError == %i\n", socket, buf, len, UDP_AddrToString(addr), e); +#else + if (errno == EWOULDBLOCK) + return 0; + Con_Printf("UDP_Write(%i, %p, %i, <%s>): errno == %i (%s)\n", socket, buf, len, UDP_AddrToString(addr), errno, strerror(errno)); +#endif + } return ret; } //============================================================================= -char *UDP_AddrToString (struct qsockaddr *addr) +char *UDP_AddrToString (const struct qsockaddr *addr) { - static char buffer[22]; - int haddr; - - haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); - sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port)); + static char buffer[22]; // only 22 needed (3 + 1 + 3 + 1 + 3 + 1 + 3 + 1 + 5 + null) + unsigned char *ip = (char *)(&((struct sockaddr_in *)addr)->sin_addr.s_addr); + sprintf(buffer, "%d.%d.%d.%d:%d", ip[0], ip[1], ip[2], ip[3], ntohs(((struct sockaddr_in *)addr)->sin_port)); return buffer; } //============================================================================= -int UDP_StringToAddr (char *string, struct qsockaddr *addr) +int UDP_StringToAddr (const char *string, struct qsockaddr *addr) { - int ha1, ha2, ha3, ha4, hp; - int ipaddr; + int ha[4], hp, ipaddr, j, numbers; + const char *colon; - sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); - ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; + hp = net_hostport; + colon = strrchr(string, ':'); + if (colon) + { + hp = atoi(colon + 1); + if (hp == 0) + hp = net_hostport; + } + numbers = sscanf(string, "%d.%d.%d.%d", &ha[0], &ha[1], &ha[2], &ha[3]); + for (ipaddr = 0, j = 0;j < numbers;j++) + ipaddr = (ipaddr << 8) | ha[j]; + // if the address is incomplete take most important numbers from myAddr + if (numbers < 4) + ipaddr |= ntohl(myAddr.i) & (-1 << (numbers * 8)); addr->sa_family = AF_INET; ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); - ((struct sockaddr_in *)addr)->sin_port = htons(hp); - return 0; + ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)hp); + if (ipaddr == INADDR_ANY) + return -1; + else + return 0; } //============================================================================= -unsigned long inet_addr(const char *cp); int UDP_GetSocketAddr (int socket, struct qsockaddr *addr) { + int ret; int addrlen = sizeof(struct qsockaddr); - unsigned int a; - memset(addr, 0, sizeof(struct qsockaddr)); - getsockname(socket, (struct sockaddr *)addr, &addrlen); - a = ((struct sockaddr_in *)addr)->sin_addr.s_addr; - if (a == 0 || a == inet_addr("127.0.0.1")) - ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr; - - return 0; + ret = getsockname(socket, (struct sockaddr *)addr, &addrlen); + if (ret == -1) + { +#ifdef WIN32 + int e = WSAGetLastError(); + Con_Printf("UDP_GetSocketAddr: WASGetLastError == %i\n", e); +#else + Con_Printf("UDP_GetSocketAddr: errno == %i (%s)\n", errno, strerror(errno)); +#endif + } + return ret; } //============================================================================= -int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name) +int UDP_GetNameFromAddr (const struct qsockaddr *addr, char *name) { struct hostent *hostentry; @@ -366,19 +442,19 @@ int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name) //============================================================================= -int UDP_GetAddrFromName(char *name, struct qsockaddr *addr) +int UDP_GetAddrFromName(const char *name, struct qsockaddr *addr) { struct hostent *hostentry; if (name[0] >= '0' && name[0] <= '9') - return PartialIPAddress (name, addr); - + return UDP_StringToAddr (name, addr); + hostentry = gethostbyname (name); if (!hostentry) return -1; addr->sa_family = AF_INET; - ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport); + ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)net_hostport); ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; return 0; @@ -386,7 +462,7 @@ int UDP_GetAddrFromName(char *name, struct qsockaddr *addr) //============================================================================= -int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) +int UDP_AddrCompare (const struct qsockaddr *addr1, const struct qsockaddr *addr2) { if (addr1->sa_family != addr2->sa_family) return -1; @@ -410,8 +486,7 @@ int UDP_GetSocketPort (struct qsockaddr *addr) int UDP_SetSocketPort (struct qsockaddr *addr, int port) { - ((struct sockaddr_in *)addr)->sin_port = htons(port); + ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)port); return 0; } -//=============================================================================