diff --git a/pokerth_game.pro b/pokerth_game.pro index 71c503cc..0f77ec7b 100644 --- a/pokerth_game.pro +++ b/pokerth_game.pro @@ -12,6 +12,7 @@ CONFIG += qt thread embed_manifest_exe warn_on debug UI_DIR = uics MOC_DIR = mocs OBJECTS_DIR = obj +DEFINES += ENABLE_IPV6 TARGET = pokerth INCLUDEPATH += . \ diff --git a/pokerth_lib.pro b/pokerth_lib.pro index 1ddf3d61..0702493c 100644 --- a/pokerth_lib.pro +++ b/pokerth_lib.pro @@ -10,6 +10,7 @@ UI_DIR = uics TARGET = lib/pokerth_lib MOC_DIR = mocs OBJECTS_DIR = obj +DEFINES += ENABLE_IPV6 QT -= core gui INCLUDEPATH += . \ diff --git a/pokerth_server.pro b/pokerth_server.pro index ec707f52..a6c1d6a6 100644 --- a/pokerth_server.pro +++ b/pokerth_server.pro @@ -11,6 +11,7 @@ TARGET = bin/pokerth_server MOC_DIR = mocs OBJECTS_DIR = obj DEFINES += POKERTH_DEDICATED_SERVER +DEFINES += ENABLE_IPV6 QT -= core gui INSTALLS += TARGET diff --git a/src/core/libircclient/include/libirc_errors.h b/src/core/libircclient/include/libirc_errors.h index 58278513..dd51e204 100644 --- a/src/core/libircclient/include/libirc_errors.h +++ b/src/core/libircclient/include/libirc_errors.h @@ -11,7 +11,7 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * - * $Id: libirc_errors.h 28 2004-10-04 10:34:58Z gyunaev $ + * $Id: libirc_errors.h 28M 2007-09-16 23:43:28Z (local) $ */ /*! @@ -193,8 +193,17 @@ #define LIBIRC_ERR_TERMINATED 15 +/*! \brief IPv6 not supported + * + * The function which requires IPv6 support was called, but the IPv6 support was not compiled + * into the application + * + * \ingroup errorcodes + */ +#define LIBIRC_ERR_NOIPV6 16 + /*! brief Internal max error value count */ -#define LIBIRC_ERR_MAX 16 +#define LIBIRC_ERR_MAX 17 #endif /* INCLUDE_IRC_ERRORS_H */ diff --git a/src/core/libircclient/include/libirc_session.h b/src/core/libircclient/include/libirc_session.h index 7acc3886..0c2398b3 100644 --- a/src/core/libircclient/include/libirc_session.h +++ b/src/core/libircclient/include/libirc_session.h @@ -11,7 +11,7 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * - * $Id: libirc_session.h 18 2004-09-14 19:50:10Z gyunaev $ + * $Id: libirc_session.h 18M 2007-09-17 01:14:31Z (local) $ */ @@ -54,7 +54,11 @@ struct irc_session_s char * username; char * nick; +#if defined( ENABLE_IPV6 ) + struct in6_addr local_addr; +#else struct in_addr local_addr; +#endif irc_dcc_t dcc_last_id; irc_dcc_session_t * dcc_sessions; port_mutex_t mutex_dcc; diff --git a/src/core/libircclient/include/libircclient.h b/src/core/libircclient/include/libircclient.h index 051d7fb3..cec9eede 100644 --- a/src/core/libircclient/include/libircclient.h +++ b/src/core/libircclient/include/libircclient.h @@ -50,6 +50,7 @@ #include /* sockaddr_in */ #else #include + #include #endif #ifdef __cplusplus @@ -228,6 +229,13 @@ int irc_connect (irc_session_t * session, const char * username, const char * realname); +int irc_connect6 (irc_session_t * session, + const char * server, + unsigned short port, + const char * server_password, + const char * nick, + const char * username, + const char * realname); /*! * \fn void irc_disconnect (irc_session_t * session) diff --git a/src/core/libircclient/src/errors.c b/src/core/libircclient/src/errors.c index f93f1085..4d31d22c 100644 --- a/src/core/libircclient/src/errors.c +++ b/src/core/libircclient/src/errors.c @@ -11,7 +11,7 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * - * $Id: errors.c 2 2004-09-08 11:49:02Z gyunaev $ + * $Id: errors.c 2M 2007-09-16 23:42:08Z (local) $ */ static const char * libirc_strerror[LIBIRC_ERR_MAX] = @@ -32,6 +32,7 @@ static const char * libirc_strerror[LIBIRC_ERR_MAX] = "Timeout error", "Could not open file", "IRC session terminated", + "IPv6 not supported", }; diff --git a/src/core/libircclient/src/libircclient.c b/src/core/libircclient/src/libircclient.c index 39bc3cc2..6b6c0ec5 100644 --- a/src/core/libircclient/src/libircclient.c +++ b/src/core/libircclient/src/libircclient.c @@ -11,10 +11,9 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * - * $Id: libircclient.c 42 2004-10-10 16:16:15Z gyunaev $ + * $Id: libircclient.c 42M 2007-09-17 01:15:57Z (local) $ */ - #include "portable.c" #include "sockets.c" @@ -27,10 +26,17 @@ #include "dcc.c" #ifdef _MSC_VER + /* + + * The debugger of MSVC 2005 does not like strdup. + * It complains about heap corruption when free is called. + * Use _strdup instead. + */ #undef strdup #define strdup _strdup #endif + #define IS_DEBUG_ENABLED(s) ((s)->option & LIBIRC_OPTION_DEBUG) @@ -133,9 +139,10 @@ int irc_connect (irc_session_t * session, session->nick = strdup (nick); session->server = strdup (server); - memset (&saddr, 0, sizeof(saddr)); + // IPv4 address resolving + memset( &saddr, 0, sizeof(saddr) ); saddr.sin_family = AF_INET; - saddr.sin_port = htons (port); + saddr.sin_port = htons (port); saddr.sin_addr.s_addr = inet_addr (server); if ( saddr.sin_addr.s_addr == INADDR_NONE ) @@ -150,7 +157,7 @@ int irc_connect (irc_session_t * session, hp = 0; #else hp = gethostbyname (server); -#endif +#endif // HAVE_GETHOSTBYNAME_R if ( !hp ) { session->lasterror = LIBIRC_ERR_RESOLV; @@ -161,7 +168,7 @@ int irc_connect (irc_session_t * session, } // create the IRC server socket - if ( socket_create (PF_INET, SOCK_STREAM, &session->sock) + if ( socket_create( PF_INET, SOCK_STREAM, &session->sock) || socket_make_nonblocking (&session->sock) ) { session->lasterror = LIBIRC_ERR_SOCKET; @@ -181,6 +188,144 @@ int irc_connect (irc_session_t * session, } + +#if defined (ENABLE_IPV6) && defined (_WIN32) + typedef int (WSAAPI * getaddrinfo_ptr_t) (const char *, const char* , const struct addrinfo *, struct addrinfo **); + typedef void (WSAAPI * freeaddrinfo_ptr_t) (struct addrinfo*); +#endif + +int irc_connect6 (irc_session_t * session, + const char * server, + unsigned short port, + const char * server_password, + const char * nick, + const char * username, + const char * realname) +{ +#if defined (ENABLE_IPV6) + struct sockaddr_in6 saddr; + struct addrinfo ainfo, *res; +#if defined (_WIN32) + int addrlen = sizeof(saddr); + HMODULE hWsock; + getaddrinfo_ptr_t getaddrinfo_ptr; + freeaddrinfo_ptr_t freeaddrinfo_ptr; + int resolvesuccess = 0; +#endif + + // Check and copy all the specified fields + if ( !server || !nick ) + { + session->lasterror = LIBIRC_ERR_INVAL; + return 1; + } + + if ( session->state != LIBIRC_STATE_INIT ) + { + session->lasterror = LIBIRC_ERR_STATE; + return 1; + } + + if ( username ) + session->username = strdup (username); + + if ( server_password ) + session->server_password = strdup (server_password); + + if ( realname ) + session->realname = strdup (realname); + + session->nick = strdup (nick); + session->server = strdup (server); + + memset( &saddr, 0, sizeof(saddr) ); + saddr.sin6_family = AF_INET6; + saddr.sin6_port = htons (port); + saddr.sin6_flowinfo = 0; + saddr.sin6_scope_id = 0; + +#if defined (_WIN32) + if ( WSAStringToAddressA( (LPSTR)server, AF_INET6, NULL, (struct sockaddr *)&saddr, &addrlen ) == SOCKET_ERROR ) + { + hWsock = LoadLibraryA("ws2_32"); + + if (hWsock) + { + // Determine functions at runtime, because windows systems < XP do not + // support getaddrinfo. + getaddrinfo_ptr = (getaddrinfo_ptr_t)GetProcAddress(hWsock, "getaddrinfo"); + freeaddrinfo_ptr = (freeaddrinfo_ptr_t)GetProcAddress(hWsock, "freeaddrinfo"); + + if (getaddrinfo_ptr && freeaddrinfo_ptr) + { + memset(&ainfo, 0, sizeof(ainfo)); + ainfo.ai_family = AF_INET6; + ainfo.ai_socktype = SOCK_STREAM; + ainfo.ai_protocol = 0; + ainfo.ai_addrlen = sizeof( saddr ); + ainfo.ai_addr = (struct sockaddr *) &saddr; + + if ( getaddrinfo_ptr(server, 0, &ainfo, &res) == 0); + { + resolvesuccess = 1; + memcpy( &saddr.sin6_addr, res->ai_addr, sizeof( saddr.sin6_addr ) ); + freeaddrinfo_ptr( res ); + } + } + FreeLibrary(hWsock); + } + if (!resolvesuccess) + { + session->lasterror = LIBIRC_ERR_RESOLV; + return 1; + } + } +#else + if ( inet_pton( AF_INET6, server, (void*) &saddr.sin6_addr ) <= 0 ) + { + memset( &ainfo, 0, sizeof(ainfo) ); + ainfo.ai_family = AF_INET6; + ainfo.ai_socktype = SOCK_STREAM; + ainfo.ai_protocol = 0; + ainfo.ai_addrlen = sizeof( saddr ); + ainfo.ai_addr = (struct sockaddr *) &saddr; + + if ( getaddrinfo( server, 0, &ainfo, &res ) ) + { + session->lasterror = LIBIRC_ERR_RESOLV; + return 1; + } + + memcpy( &saddr.sin6_addr, res->ai_addr, sizeof( saddr.sin6_addr ) ); + freeaddrinfo( res ); + } +#endif + + // create the IRC server socket + if ( socket_create( PF_INET6, SOCK_STREAM, &session->sock) + || socket_make_nonblocking (&session->sock) ) + { + session->lasterror = LIBIRC_ERR_SOCKET; + return 1; + } + + // and connect to the IRC server + if ( socket_connect (&session->sock, (struct sockaddr *) &saddr, sizeof(saddr)) ) + { + session->lasterror = LIBIRC_ERR_CONNECT; + return 1; + } + + session->state = LIBIRC_STATE_CONNECTING; + session->motd_received = 0; // reset in case of reconnect + return 0; +#else + session->lasterror = LIBIRC_ERR_NOIPV6; + return 1; +#endif +} + + int irc_is_connected (irc_session_t * session) { return (session->state == LIBIRC_STATE_CONNECTED @@ -279,7 +424,7 @@ static void libirc_process_incoming_data (irc_session_t * session, int process_l memcpy (buf, session->incoming_buf, process_length); buf[process_length] = '\0'; - memset (params, 0, sizeof(params)); + memset ((char *)params, 0, sizeof(params)); p = buf; /* diff --git a/src/core/libircclient/src/portable.c b/src/core/libircclient/src/portable.c index fc44e767..09ae728e 100644 --- a/src/core/libircclient/src/portable.c +++ b/src/core/libircclient/src/portable.c @@ -43,6 +43,7 @@ #endif #else #include + #include #include #include #include diff --git a/src/core/libircclient/src/sockets.c b/src/core/libircclient/src/sockets.c index 164140f1..7423b778 100644 --- a/src/core/libircclient/src/sockets.c +++ b/src/core/libircclient/src/sockets.c @@ -11,7 +11,7 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * - * $Id: sockets.c 53 2004-10-17 11:16:03Z gyunaev $ + * $Id: sockets.c 53M 2007-09-16 23:57:59Z (local) $ */ /* @@ -28,8 +28,9 @@ typedef int socket_t; #else + #include + #include #include - #include #define IS_SOCKET_ERROR(a) ((a)==SOCKET_ERROR) @@ -37,7 +38,6 @@ #define EINPROGRESS WSAEINPROGRESS #define EINTR WSAEINTR - typedef unsigned int socklen_t; typedef SOCKET socket_t; #endif @@ -59,7 +59,7 @@ static int socket_error() static int socket_create (int domain, int type, socket_t * sock) { - *sock = socket (PF_INET, SOCK_STREAM, 0); + *sock = socket (domain, type, 0); return IS_SOCKET_ERROR(*sock) ? 1 : 0; } diff --git a/src/net/common/ircthread.cpp b/src/net/common/ircthread.cpp index ee76f4f5..2b52d178 100644 --- a/src/net/common/ircthread.cpp +++ b/src/net/common/ircthread.cpp @@ -316,7 +316,13 @@ IrcThread::Main() irc_session_t *s = context.session; if (s) { - if (irc_connect(s, context.serverAddress.c_str(), context.serverPort, 0, context.nick.c_str(), 0, 0) != 0) + bool connected = false; + if (context.useIPv6) + connected = irc_connect6(s, context.serverAddress.c_str(), context.serverPort, 0, context.nick.c_str(), 0, 0) == 0; + else + connected = irc_connect(s, context.serverAddress.c_str(), context.serverPort, 0, context.nick.c_str(), 0, 0) == 0; + + if (!connected) HandleIrcError(irc_errno(s)); else {