summaryrefslogtreecommitdiff
path: root/src/common/socket.c
diff options
context:
space:
mode:
authorFlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-01-06 12:11:50 +0000
committerFlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-01-06 12:11:50 +0000
commit250672ef201106afb563a2e3bbd79a4ab98d13cc (patch)
tree7501da76a93047c2dfb79bcb338c9379e4abb15a /src/common/socket.c
parentf044795aa8967ff4d99c3579553474d6bab4bf90 (diff)
downloadhercules-250672ef201106afb563a2e3bbd79a4ab98d13cc.tar.gz
hercules-250672ef201106afb563a2e3bbd79a4ab98d13cc.tar.bz2
hercules-250672ef201106afb563a2e3bbd79a4ab98d13cc.tar.xz
hercules-250672ef201106afb563a2e3bbd79a4ab98d13cc.zip
- 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
Diffstat (limited to 'src/common/socket.c')
-rw-r--r--src/common/socket.c189
1 files changed, 112 insertions, 77 deletions
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 <windows.h>
- #include <winsock.h>
+ #include <winsock2.h>
#include <io.h>
#else
#include <errno.h>
@@ -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);