From 250672ef201106afb563a2e3bbd79a4ab98d13cc Mon Sep 17 00:00:00 2001 From: FlavioJS Date: Sat, 6 Jan 2007 12:11:50 +0000 Subject: - Now winsock 2 is required. - Cleaned up do_close and socket_init a bit. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@9621 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/common/socket.c | 189 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 112 insertions(+), 77 deletions(-) (limited to 'src/common/socket.c') diff --git a/src/common/socket.c b/src/common/socket.c index 829bd1a56..a230158c8 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -8,7 +8,7 @@ #ifdef __WIN32 #define WIN32_LEAN_AND_MEAN #include - #include + #include #include #else #include @@ -56,6 +56,13 @@ #include "../common/malloc.h" #include "../common/showmsg.h" +/// shutdown() constants +#if defined(SD_RECEIVE) && !defined(SHUT_RD) +#define SHUT_RD SD_RECEIVE +#define SHUT_WR SD_SEND +#define SHUT_RDWR SD_BOTH +#endif + fd_set readfds; int fd_max; time_t last_tick; @@ -1059,8 +1066,8 @@ int RFIFOSKIP(int fd,int len) } -unsigned int addr_[16]; // ip addresses of local host (host byte order) -unsigned int naddr_ = 0; // # of ip addresses +uint32 addr_[16]; // ip addresses of local host (host byte order) +int naddr_ = 0; // # of ip addresses void socket_final (void) { @@ -1092,97 +1099,125 @@ void socket_final (void) aFree(session[0]); } -//Closes a socket. -//Needed to simplify shutdown code as well as manage the subtle differences in socket management from Windows and *nix. +/// Closes a socket. void do_close(int fd) { -//We don't really care if these closing functions return an error, we are just shutting down and not reusing this socket. -#ifdef __WIN32 -// shutdown(fd, SD_BOTH); //FIXME: Shutdown requires winsock2.h! What would be the proper shutting down method for winsock1? - flush_fifo(fd); // try to send what's left (although it might not succeed since it's a nonblocking socket) -#endif - closesocket(fd); + flush_fifo(fd); // Try to send what's left (although it might not succeed since it's a nonblocking socket) + shutdown(fd, SHUT_RDWR); // Disallow further reads/writes + closesocket(fd); // We don't really care if these closing functions return an error, we are just shutting down and not reusing this socket. if (session[fd]) delete_session(fd); } -void socket_init (void) +/// Retrieve local ips in host byte order. +/// Uses loopback is no address is found. +int socket_getips(uint32 *ips, int max) { - char *SOCKET_CONF_FILENAME = "conf/packet_athena.conf"; -#ifdef __WIN32 - char** a; - unsigned int i; - char fullhost[255]; - struct hostent* hent; - - /* Start up the windows networking */ - WORD version_wanted = MAKEWORD(1, 1); //Demand at least WinSocket version 1.1 (from Freya) - WSADATA wsaData; - - if ( WSAStartup(version_wanted, &wsaData) != 0 ) { - ShowFatalError("SYSERR: WinSock not available!\n"); - exit(1); - } - - if(gethostname(fullhost, sizeof(fullhost)) == SOCKET_ERROR) { - ShowError("Ugg.. no hostname defined!\n"); - return; - } + int num = 0; - // XXX This should look up the local IP addresses in the registry - // instead of calling gethostbyname. However, the way IP addresses - // are stored in the registry is annoyingly complex, so I'll leave - // this as T.B.D. - hent = gethostbyname(fullhost); - if (hent == NULL) { - ShowError("Cannot resolve our own hostname to a IP address"); - return; - } + if( ips == NULL || max <= 0 ) + return 0; - a = hent->h_addr_list; - for(i = 0; a[i] != 0 && i < 16; ++i) { - unsigned long addr1 = ntohl(*(unsigned long*) a[i]); - addr_[i] = addr1; +#ifdef WIN32 + { + char fullhost[255]; + u_long** a; + struct hostent* hent; + + // XXX This should look up the local IP addresses in the registry + // instead of calling gethostbyname. However, the way IP addresses + // are stored in the registry is annoyingly complex, so I'll leave + // this as T.B.D. [Meruru] + if( gethostname(fullhost, sizeof(fullhost)) == SOCKET_ERROR ) + { + ShowError("socket_getips: No hostname defined!\n"); + return 0; + } + else + { + hent = gethostbyname(fullhost); + if( hent == NULL ){ + ShowError("socket_getips: Cannot resolve our own hostname to a IP address\n"); + return 0; + } + a = (u_long**)hent->h_addr_list; + for( ; a[num] != NULL && num < max; ++num) + ips[num] = (uint32)ntohl(*a[num]); + } } - naddr_ = i; -#else - int pos; - int fdes = socket(AF_INET, SOCK_STREAM, 0); - char buf[16 * sizeof(struct ifreq)]; - struct ifconf ic; - - // The ioctl call will fail with Invalid Argument if there are more - // interfaces than will fit in the buffer - ic.ifc_len = sizeof(buf); - ic.ifc_buf = buf; - if(ioctl(fdes, SIOCGIFCONF, &ic) == -1) { - ShowError("SIOCGIFCONF failed!\n"); - return; +#else // not WIN32 + { + int pos; + int fd; + char buf[2*16*sizeof(struct ifreq)]; + struct ifconf ic; + struct ifreq* ir; + struct sockaddr_in* a; + u_long ad; + + fd = socket(AF_INET, SOCK_STREAM, 0); + + // The ioctl call will fail with Invalid Argument if there are more + // interfaces than will fit in the buffer + ic.ifc_len = sizeof(buf); + ic.ifc_buf = buf; + if( ioctl(fd, SIOCGIFCONF, &ic) == -1 ) + { + ShowError("socket_getips: SIOCGIFCONF failed!\n"); + return 0; + } + else + { + for( pos=0; pos < ic.ifc_len && num < max; ) + { + ir = (struct ifreq*)(buf+pos); + a = (struct sockaddr_in*) &(ir->ifr_addr); + if( a->sin_family == AF_INET ){ + ad = ntohl(a->sin_addr.s_addr); + if( ad != INADDR_LOOPBACK && ad != INADDR_ANY ) + ips[num++] = (uint32)ad; + } + #if (defined(BSD) && BSD >= 199103) || defined(_AIX) || defined(__APPLE__) + pos += ir->ifr_addr.sa_len + sizeof(ir->ifr_name); + #else// not AIX or APPLE + pos += sizeof(struct ifreq); + #endif//not AIX or APPLE + } + } + closesocket(fd); } +#endif // not W32 - for(pos = 0; pos < ic.ifc_len;) - { - struct ifreq * ir = (struct ifreq *) (ic.ifc_buf + pos); + // Use loopback if no ips are found + if( num == 0 ) + ips[num++] = (uint32)INADDR_LOOPBACK; - struct sockaddr_in * a = (struct sockaddr_in *) &(ir->ifr_addr); + return num; +} - if(a->sin_family == AF_INET) { - u_long ad = ntohl(a->sin_addr.s_addr); - if(ad != INADDR_LOOPBACK && ad != INADDR_ANY) { - addr_[naddr_ ++] = ad; - if(naddr_ == 16) - break; - } +void socket_init(void) +{ + char *SOCKET_CONF_FILENAME = "conf/packet_athena.conf"; + +#ifdef WIN32 + {// Start up windows networking + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(2, 0); + if( WSAStartup(wVersionRequested, &wsaData) != 0 ) + { + ShowError("socket_init: WinSock not available!\n"); + return; + } + if( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0 ) + { + printf("socket_init: WinSock version mismatch (2.0 or compatible required)!\n"); + return; } - - #if defined(_AIX) || defined(__APPLE__) - pos += ir->ifr_addr.sa_len; // For when we port athena to run on Mac's :) - pos += sizeof(ir->ifr_name); - #else - pos += sizeof(struct ifreq); - #endif } #endif + // Get initial local ips + naddr_ = socket_getips(addr_,16); + FD_ZERO(&readfds); socket_config_read(SOCKET_CONF_FILENAME); -- cgit v1.2.3-60-g2f50