Revision 2919

View differences:

libsylph/socket.c
1 1
/*
2 2
 * LibSylph -- E-Mail client library
3
 * Copyright (C) 1999-2009 Hiroyuki Yamamoto
3
 * Copyright (C) 1999-2011 Hiroyuki Yamamoto
4 4
 *
5 5
 * This library is free software; you can redistribute it and/or
6 6
 * modify it under the terms of the GNU Lesser General Public
......
150 150
					 const gchar	*hostname,
151 151
					 gushort	 port);
152 152
#else
153
#ifdef G_OS_WIN32
154
typedef int (*GetAddrInfoFunc)		(const char	*node,
155
					 const char	*service,
156
					 const struct addrinfo *hints,
157
					 struct addrinfo **res);
158
typedef void (*FreeAddrInfoFunc)	(struct addrinfo *res);
159

  
160
static GetAddrInfoFunc getaddrinfo_func = NULL;
161
static FreeAddrInfoFunc freeaddrinfo_func = NULL;
162

  
163
#undef getaddrinfo
164
#define getaddrinfo	my_getaddrinfo
165
#undef freeaddrinfo
166
#define freeaddrinfo	my_freeaddrinfo
167
#endif
168

  
153 169
static SockDesc sock_connect_by_getaddrinfo	(const gchar	*hostname,
154 170
						 gushort	 port);
155 171
#endif
......
777 793
#endif
778 794
}
779 795

  
780
#ifndef INET6
796
#if !defined(INET6) || defined(G_OS_WIN32)
781 797
static gint my_inet_aton(const gchar *hostname, struct in_addr *inp)
782 798
{
783 799
#if HAVE_INET_ATON
......
797 813
#endif
798 814
#endif /* HAVE_INET_ATON */
799 815
}
816
#endif /* !defined(INET6) || defined(G_OS_WIN32) */
800 817

  
818
#ifndef INET6
801 819
static gint sock_connect_by_hostname(gint sock, const gchar *hostname,
802 820
				     gushort port)
803 821
{
......
833 851
#else /* INET6 */
834 852

  
835 853
#ifdef G_OS_WIN32
854
static gboolean win32_ipv6_supported(void)
855
{
856
	static gboolean ipv6_checked = FALSE;
857
	HMODULE hmodule;
858

  
859
	if (ipv6_checked)
860
		return getaddrinfo_func != NULL;
861

  
862
	hmodule = GetModuleHandleA("ws2_32");
863
	if (hmodule) {
864
		getaddrinfo_func =
865
			(GetAddrInfoFunc)GetProcAddress(hmodule, "getaddrinfo");
866
		freeaddrinfo_func =
867
			(FreeAddrInfoFunc)GetProcAddress(hmodule, "freeaddrinfo");
868
		if (!getaddrinfo_func || !freeaddrinfo_func) {
869
			getaddrinfo_func = NULL;
870
			freeaddrinfo_func = NULL;
871
		}
872
	}
873

  
874
	if (getaddrinfo_func)
875
		debug_print("ws2_32 has IPv6 functions.\n");
876
	else
877
		debug_print("ws2_32 does not have IPv6 functions.\n");
878

  
879
	ipv6_checked = TRUE;
880
	return getaddrinfo_func != NULL;
881
}
882

  
883
/* subset of getaddrinfo() */
884
static int my_getaddrinfo(const char *node, const char *service,
885
			  const struct addrinfo *hintp,
886
			  struct addrinfo **res)
887
{
888
	struct addrinfo *ai;
889
	struct sockaddr_in addr, *paddr;
890
	struct addrinfo hints;
891
	gint port = 0;
892

  
893
	if (win32_ipv6_supported())
894
		return getaddrinfo_func(node, service, hintp, res);
895

  
896
	if (!hintp) {
897
		memset(&hints, 0, sizeof(hints));
898
		hints.ai_family = AF_INET;
899
		hints.ai_socktype = SOCK_STREAM;
900
	} else
901
		memcpy(&hints, hintp, sizeof(hints));
902

  
903
	if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
904
		return EAI_FAMILY;
905
	if (hints.ai_socktype == 0)
906
		hints.ai_socktype = SOCK_STREAM;
907
	if (hints.ai_protocol == 0)
908
		hints.ai_protocol = IPPROTO_TCP;
909
	if (hints.ai_socktype != SOCK_STREAM)
910
		return EAI_SOCKTYPE;
911
	if (hints.ai_protocol != IPPROTO_TCP)
912
		return EAI_SOCKTYPE;
913
#if 0
914
	if (!node && !service)
915
		return EAI_NONAME;
916
#endif
917
	if (!node || !service)
918
		return EAI_NONAME;
919

  
920
	port = atoi(service);
921

  
922
	memset(&addr, 0, sizeof(addr));
923
	addr.sin_family = AF_INET;
924
	addr.sin_port = htons(port);
925

  
926
	if (!my_inet_aton(node, &addr.sin_addr)) {
927
		struct hostent *hp;
928

  
929
		if ((hp = my_gethostbyname(node)) == NULL) {
930
			fprintf(stderr, "%s: unknown host.\n", node);
931
			errno = 0;
932
			return EAI_NONAME;
933
		}
934
		if (hp->h_length != 4 && hp->h_length != 8) {
935
			fprintf(stderr, "illegal address length received for host %s\n", node);
936
			errno = 0;
937
			return EAI_FAIL;
938
		}
939

  
940
		memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
941
	}
942

  
943
	ai = g_malloc0(sizeof(struct addrinfo));
944
	paddr = g_malloc0(sizeof(struct sockaddr_in));
945
	memcpy(paddr, &addr, sizeof(struct sockaddr_in));
946

  
947
	ai->ai_flags = 0;
948
	ai->ai_family = AF_INET;
949
	ai->ai_socktype = hints.ai_socktype;
950
	ai->ai_protocol = hints.ai_protocol;
951
	ai->ai_addrlen = sizeof(struct sockaddr_in);
952
	ai->ai_addr = (struct sockaddr *)paddr;
953
	ai->ai_canonname = NULL;
954
	ai->ai_next = NULL;
955

  
956
	*res = ai;
957

  
958
	return 0;
959
}
960

  
961
static void my_freeaddrinfo(struct addrinfo *res)
962
{
963
	if (win32_ipv6_supported()) {
964
		freeaddrinfo_func(res);
965
		return;
966
	}
967

  
968
	if (res) {
969
		g_free(res->ai_addr);
970
		g_free(res);
971
	}
972
}
973

  
836 974
/* MinGW defines gai_strerror() in ws2tcpip.h, but it is not implemented. */
837 975
#undef gai_strerror
838 976
const gchar *gai_strerror(gint errcode)
makewin32.sh
4 4
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/local/include
5 5

  
6 6
./configure --prefix=$HOME/dist --with-localedir=lib/locale \
7
  --enable-oniguruma --enable-threads --disable-ipv6 \
7
  --enable-oniguruma --enable-threads \
8 8
  'CC=gcc -mtune=pentium3' CFLAGS=-O3 \
9 9
  && make \
10 10
  && make install-strip \
ChangeLog
1
2011-06-29
2

  
3
	* libsylph/socket.c: win32: supported IPv6 with fallback implementation
4
	  for Windows 2000.
5
	* makewin32.sh: enabled IPv6.
6

  
1 7
2011-06-28
2 8

  
3 9
	* src/foldersel.c: removed alloca() calls.

Also available in: Unified diff