IRC IPv6 support.

This commit is contained in:
lotodore
2007-10-08 11:07:32 +00:00
parent d11b35a1a7
commit d0ccc68d1f
11 changed files with 193 additions and 16 deletions
+11 -2
View File
@@ -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 */
@@ -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;
@@ -50,6 +50,7 @@
#include <netinet/in.h> /* sockaddr_in */
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#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)
+2 -1
View File
@@ -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",
};
+152 -7
View File
@@ -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;
/*
+1
View File
@@ -43,6 +43,7 @@
#endif
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <time.h>
#include <stdio.h>
+4 -4
View File
@@ -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 <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <winsock.h>
#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;
}