Revision 2919 libsylph/socket.c
| socket.c (revision 2919) | ||
|---|---|---|
| 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) |
Also available in: Unified diff