PATCH: getaddrinfo
Marcus Meissner
marcus at jet.franken.de
Wed Nov 16 11:44:46 CST 2005
Hi,
This patch implements getaddrinfo(), with hopefully
all concerns addressed.
Opera.exe was the reference application.
Ciao, Marcus
Changelog:
Implemented getaddrinfo(), including full mapping of struct
addrinfo between UNIX and Windows.
Based on a patch by Mike Hearn.
Index: configure.ac
===================================================================
RCS file: /home/wine/wine/configure.ac,v
retrieving revision 1.413
diff -u -r1.413 configure.ac
--- configure.ac 16 Nov 2005 11:45:52 -0000 1.413
+++ configure.ac 16 Nov 2005 17:42:28 -0000
@@ -1158,6 +1158,7 @@
ftruncate \
futimes \
futimesat \
+ getaddrinfo \
getnetbyname \
getopt_long \
getpagesize \
Index: include/ws2tcpip.h
===================================================================
RCS file: /home/wine/wine/include/ws2tcpip.h,v
retrieving revision 1.6
diff -u -r1.6 ws2tcpip.h
--- include/ws2tcpip.h 16 Nov 2005 11:21:57 -0000 1.6
+++ include/ws2tcpip.h 16 Nov 2005 17:42:29 -0000
@@ -159,4 +159,35 @@
#define WS_IP_DONTFRAGMENT 14
#endif /* USE_WS_PREFIX */
+/* Possible Windows flags for getaddrinfo() */
+#ifndef USE_WS_PREFIX
+# define AI_PASSIVE 0x0001
+# define AI_CANONNAME 0x0002
+# define AI_NUMERICHOST 0x0004
+/* getaddrinfo error codes */
+# define EAI_AGAIN WSATRY_AGAIN
+# define EAI_BADFLAGS WSAEINVAL
+# define EAI_FAIL WSANO_RECOVERY
+# define EAI_FAMILY WSAEAFNOSUPPORT
+# define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
+# define EAI_NODATA WSANO_DATA
+# define EAI_NONAME WSAHOST_NOT_FOUND
+# define EAI_SERVICE WSATYPE_NOT_FOUND
+# define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
+#else
+# define WS_AI_PASSIVE 0x0001
+# define WS_AI_CANONNAME 0x0002
+# define WS_AI_NUMERICHOST 0x0004
+/* getaddrinfo error codes */
+# define WS_EAI_AGAIN WSATRY_AGAIN
+# define WS_EAI_BADFLAGS WSAEINVAL
+# define WS_EAI_FAIL WSANO_RECOVERY
+# define WS_EAI_FAMILY WSAEAFNOSUPPORT
+# define WS_EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
+# define WS_EAI_NODATA WSANO_DATA
+# define WS_EAI_NONAME WSAHOST_NOT_FOUND
+# define WS_EAI_SERVICE WSATYPE_NOT_FOUND
+# define WS_EAI_SOCKTYPE WSAESOCKTNOSUPPORT
+#endif
+
#endif /* __WS2TCPIP__ */
Index: dlls/winsock/socket.c
===================================================================
RCS file: /home/wine/wine/dlls/winsock/socket.c,v
retrieving revision 1.194
diff -u -r1.194 socket.c
--- dlls/winsock/socket.c 16 Nov 2005 11:21:57 -0000 1.194
+++ dlls/winsock/socket.c 16 Nov 2005 17:42:31 -0000
@@ -314,6 +314,30 @@
{ 0, 0 }
};
+static const int ws_aiflag_map[][2] =
+{
+ MAP_OPTION( AI_PASSIVE ),
+ MAP_OPTION( AI_CANONNAME ),
+ MAP_OPTION( AI_NUMERICHOST ),
+ /* Linux/UNIX knows a lot more. But Windows only
+ * has 3 as far as I could see. -Marcus
+ */
+ { 0, 0 }
+};
+
+static const int ws_eai_map[][2] =
+{
+ MAP_OPTION( EAI_AGAIN ),
+ MAP_OPTION( EAI_BADFLAGS ),
+ MAP_OPTION( EAI_FAIL ),
+ MAP_OPTION( EAI_FAMILY ),
+ MAP_OPTION( EAI_MEMORY ),
+ MAP_OPTION( EAI_NODATA ),
+ MAP_OPTION( EAI_SERVICE ),
+ MAP_OPTION( EAI_SOCKTYPE ),
+ { 0, 0 }
+};
+
inline static DWORD NtStatusToWSAError( const DWORD status )
{
/* We only need to cover the status codes set by server async request handling */
@@ -860,9 +884,9 @@
/* ----------------------------------- i/o APIs */
#ifdef HAVE_IPX
-#define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
+#define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX || (pf) == WS_AF_INET6)
#else
-#define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
+#define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf) == WS_AF_INET6)
#endif
@@ -3031,6 +3055,173 @@
return retval;
}
+/***********************************************************************
+ * freeaddrinfo (WS2_32.@)
+ */
+void WINAPI WS_freeaddrinfo(struct WS_addrinfo *res)
+{
+ while (res) {
+ struct WS_addrinfo *next;
+
+ if (res->ai_canonname)
+ HeapFree(GetProcessHeap(),0,res->ai_canonname);
+ if (res->ai_addr)
+ HeapFree(GetProcessHeap(),0,res->ai_addr);
+ next = res->ai_next;
+ HeapFree(GetProcessHeap(),0,res);
+ res = next;
+ }
+}
+
+/* helper functions for getaddrinfo() */
+static int convert_aiflag_w2u(int winflags) {
+ int i, unixflags = 0;
+
+ for (i=0;ws_aiflag_map[i][0];i++) {
+ if (ws_aiflag_map[i][0] & winflags) {
+ unixflags |= ws_aiflag_map[i][1];
+ winflags &= ~ws_aiflag_map[i][0];
+ }
+ }
+ if (winflags)
+ FIXME("Unhandled windows AI_xxx flags %x\n", winflags);
+ return unixflags;
+}
+
+static int convert_aiflag_u2w(int unixflags) {
+ int i, winflags = 0;
+
+ for (i=0;ws_aiflag_map[i][0];i++) {
+ if (ws_aiflag_map[i][1] & unixflags) {
+ winflags |= ws_aiflag_map[i][0];
+ unixflags &= ~ws_aiflag_map[i][1];
+ }
+ }
+ if (unixflags) /* will warn usually */
+ WARN("Unhandled UNIX AI_xxx flags %x\n", unixflags);
+ return winflags;
+}
+
+static int convert_eai_u2w(int unixret) {
+ int i;
+
+ for (i=0;ws_eai_map[i][0];i++)
+ if (ws_eai_map[i][0] == unixret)
+ return ws_eai_map[i][1];
+ return unixret;
+}
+
+/***********************************************************************
+ * GetAddrInfoA (WS2_32.@)
+ * getaddrinfo (WS2_32.@)
+ */
+int WINAPI GetAddrInfoA(const CHAR *nodename, const CHAR *servname,
+ const struct WS_addrinfo *hints, struct WS_addrinfo **res)
+{
+#if HAVE_GETADDRINFO
+ struct addrinfo *unixaires = NULL;
+ int result;
+ struct addrinfo unixhints, *punixhints = NULL;
+ CHAR *node = NULL, *serv = NULL;
+
+ if (nodename)
+ if (!(node = strdup_lower(nodename))) return WSA_NOT_ENOUGH_MEMORY;
+
+ if (servname) {
+ if (!(serv = strdup_lower(servname))) {
+ if (node) HeapFree(GetProcessHeap(), 0, node);
+ return WSA_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ if (hints) {
+ punixhints = &unixhints;
+
+ memset(&unixhints, 0, sizeof(unixhints));
+ punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
+ punixhints->ai_family = convert_af_w2u(hints->ai_family);
+ punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
+ punixhints->ai_protocol = convert_proto_w2u(hints->ai_protocol);
+ }
+
+ /* getaddrinfo(3) is thread safe, no need to wrap in CS */
+ result = getaddrinfo(nodename, servname, punixhints, &unixaires);
+
+ TRACE("%s, %s %p -> %p %d\n", nodename, servname, hints, res, result);
+
+ if (node) HeapFree(GetProcessHeap(), 0, node);
+ if (serv) HeapFree(GetProcessHeap(), 0, serv);
+
+ if (!result) {
+ struct addrinfo *xuai = unixaires;
+ struct WS_addrinfo **xai = res;
+
+ *xai = NULL;
+ while (xuai) {
+ struct WS_addrinfo *ai = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo));
+ int len;
+
+ if (!ai)
+ goto outofmem;
+
+ *xai = ai;xai = &ai->ai_next;
+ ai->ai_flags = convert_aiflag_u2w(xuai->ai_flags);
+ ai->ai_family = convert_af_u2w(xuai->ai_family);
+ ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
+ ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
+ if (xuai->ai_canonname) {
+ TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
+ ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
+ if (!ai->ai_canonname)
+ goto outofmem;
+ strcpy(ai->ai_canonname,xuai->ai_canonname);
+ }
+ len = xuai->ai_addrlen;
+ ai->ai_addr = HeapAlloc(GetProcessHeap(),0,len);
+ if (!ai->ai_addr)
+ goto outofmem;
+ ai->ai_addrlen = len;
+ do {
+ int winlen = ai->ai_addrlen;
+
+ if (!ws_sockaddr_u2ws(xuai->ai_addr, xuai->ai_addrlen, ai->ai_addr, &winlen)) {
+ ai->ai_addrlen = winlen;
+ break;
+ }
+ len = 2*len;
+ ai->ai_addr = HeapReAlloc(GetProcessHeap(),0,ai->ai_addr,len);
+ if (!ai->ai_addr)
+ goto outofmem;
+ ai->ai_addrlen = len;
+ } while (1);
+ xuai = xuai->ai_next;
+ }
+ freeaddrinfo(unixaires);
+ } else {
+ result = convert_eai_u2w(result);
+ }
+ return result;
+
+outofmem:
+ if (*res) WS_freeaddrinfo(*res);
+ if (unixaires) freeaddrinfo(unixaires);
+ *res = NULL;
+ return WSA_NOT_ENOUGH_MEMORY;
+#else
+ FIXME("getaddrinfo() failed, not found during buildtime.\n");
+ return EAI_FAIL;
+#endif
+}
+
+/***********************************************************************
+ * GetAddrInfoW (WS2_32.@)
+ */
+int WINAPI GetAddrInfoW(WCHAR *nodename, WCHAR *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ FIXME("empty stub!\n");
+ return EAI_FAIL;
+}
/***********************************************************************
* getservbyport (WS2_32.56)
Index: dlls/winsock/ws2_32.spec
===================================================================
RCS file: /home/wine/wine/dlls/winsock/ws2_32.spec,v
retrieving revision 1.42
diff -u -r1.42 ws2_32.spec
--- dlls/winsock/ws2_32.spec 1 Aug 2005 10:56:49 -0000 1.42
+++ dlls/winsock/ws2_32.spec 16 Nov 2005 17:42:31 -0000
@@ -113,6 +113,8 @@
@ stub WSCUpdateProvider
@ stub WSCWriteNameSpaceOrder
@ stdcall WSCWriteProviderOrder(ptr long)
-@ stub freeaddrinfo
-@ stub getaddrinfo
+@ stdcall freeaddrinfo(ptr) WS_freeaddrinfo
+@ stdcall getaddrinfo(str str ptr ptr) GetAddrInfoA
+@ stdcall GetAddrInfoW(wstr wstr ptr ptr)
+@ stdcall GetAddrInfoA(str str ptr ptr)
@ stub getnameinfo
More information about the wine-patches
mailing list