Mercurial > pidgin.yaz
diff libpurple/protocols/gg/lib/resolver.c @ 32763:326591e64aaa
Gadu-Gadu: move our win32 resolver out of libgadu sources. Refs #343
author | tomkiewicz@cpw.pidgin.im |
---|---|
date | Mon, 17 Oct 2011 21:25:53 +0000 |
parents | b8646c6ae19a |
children | ef01f180114b |
line wrap: on
line diff
--- a/libpurple/protocols/gg/lib/resolver.c Mon Oct 17 20:09:23 2011 +0000 +++ b/libpurple/protocols/gg/lib/resolver.c Mon Oct 17 21:25:53 2011 +0000 @@ -319,283 +319,6 @@ int pid; /*< Identyfikator procesu */ }; -#ifdef _WIN32 -/** - * Deal with the fact that you can't select() on a win32 file fd. - * This makes it practically impossible to tie into purple's event loop. - * - * -This is thanks to Tor Lillqvist. - * XXX - Move this to where the rest of the the win32 compatiblity stuff goes when we push the changes back to libgadu. - */ -static int -socket_pipe (int *fds) -{ - SOCKET temp, socket1 = -1, socket2 = -1; - struct sockaddr_in saddr; - int len; - u_long arg; - fd_set read_set, write_set; - struct timeval tv; - - temp = socket(AF_INET, SOCK_STREAM, 0); - - if (temp == INVALID_SOCKET) { - goto out0; - } - - arg = 1; - if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) { - goto out0; - } - - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_port = 0; - saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) { - goto out0; - } - - if (listen(temp, 1) == SOCKET_ERROR) { - goto out0; - } - - len = sizeof(saddr); - if (getsockname(temp, (struct sockaddr *)&saddr, &len)) { - goto out0; - } - - socket1 = socket(AF_INET, SOCK_STREAM, 0); - - if (socket1 == INVALID_SOCKET) { - goto out0; - } - - arg = 1; - if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) { - goto out1; - } - - if (connect(socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR || - WSAGetLastError() != WSAEWOULDBLOCK) { - goto out1; - } - - FD_ZERO(&read_set); - FD_SET(temp, &read_set); - - tv.tv_sec = 0; - tv.tv_usec = 0; - - if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) { - goto out1; - } - - if (!FD_ISSET(temp, &read_set)) { - goto out1; - } - - socket2 = accept(temp, (struct sockaddr *) &saddr, &len); - if (socket2 == INVALID_SOCKET) { - goto out1; - } - - FD_ZERO(&write_set); - FD_SET(socket1, &write_set); - - tv.tv_sec = 0; - tv.tv_usec = 0; - - if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) { - goto out2; - } - - if (!FD_ISSET(socket1, &write_set)) { - goto out2; - } - - arg = 0; - if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) { - goto out2; - } - - arg = 0; - if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) { - goto out2; - } - - fds[0] = socket1; - fds[1] = socket2; - - closesocket (temp); - - return 0; - -out2: - closesocket (socket2); -out1: - closesocket (socket1); -out0: - closesocket (temp); - errno = EIO; /* XXX */ - - return -1; -} -#endif - - - -#ifdef _WIN32 -struct gg_resolve_win32thread_data { - char *hostname; - int fd; -}; - -static DWORD WINAPI gg_resolve_win32thread_thread(LPVOID arg) -{ - struct gg_resolve_win32thread_data *d = arg; - struct in_addr addr_ip[2], *addr_list; - int addr_count; - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() host: %s, fd: %i called\n", d->hostname, d->fd); - - if ((addr_ip[0].s_addr = inet_addr(d->hostname)) == INADDR_NONE) { - /* W przypadku błędu gg_gethostbyname_real() zwróci -1 - * i nie zmieni &addr. Tam jest już INADDR_NONE, - * więc nie musimy robić nic więcej. */ - if (gg_gethostbyname_real(d->hostname, &addr_list, &addr_count, 0) == -1) - { - addr_list = addr_ip; - } - } else { - addr_list = addr_ip; - addr_ip[1].s_addr = INADDR_NONE; - addr_count = 1; - } - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() count = %d\n", addr_count); - - write(d->fd, addr_list, (addr_count+1) * sizeof(struct in_addr)); - close(d->fd); - - free(d->hostname); - d->hostname = NULL; - - free(d); - - if (addr_list != addr_ip) - free(addr_list); - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() done\n"); - - return 0; -} - - -static int gg_resolve_win32thread(int *fd, void **resolver, const char *hostname) -{ - struct gg_resolve_win32thread_data *d = NULL; - HANDLE h; - DWORD dwTId; - int pipes[2], new_errno; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_win32thread(%p, %p, \"%s\");\n", fd, resolver, hostname); - - if (!resolver || !fd || !hostname) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() creating pipes...\n"); - - if (socket_pipe(pipes) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno)); - return -1; - } - - if (!(d = malloc(sizeof(*d)))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n"); - new_errno = errno; - goto cleanup; - } - - d->hostname = NULL; - - if (!(d->hostname = strdup(hostname))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n"); - new_errno = errno; - goto cleanup; - } - - d->fd = pipes[1]; - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() creating thread...\n"); - - h = CreateThread(NULL, 0, gg_resolve_win32thread_thread, - d, 0, &dwTId); - - if (h == NULL) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create thread\n"); - new_errno = errno; - goto cleanup; - } - - *resolver = h; - *fd = pipes[0]; - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() done\n"); - - return 0; - -cleanup: - if (d) { - free(d->hostname); - free(d); - } - - close(pipes[0]); - close(pipes[1]); - - errno = new_errno; - - return -1; - -} - -static void gg_resolve_win32thread_cleanup(void **priv_data, int force) -{ - struct gg_resolve_win32thread_data *data; - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force: %i called\n", force); - - if (priv_data == NULL || *priv_data == NULL) - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() priv_data: NULL\n"); - return; - - data = (struct gg_resolve_win32thread_data*) *priv_data; - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() data: %s called\n", data->hostname); - *priv_data = NULL; - - if (force) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force called\n", force); - //pthread_cancel(data->thread); - //pthread_join(data->thread, NULL); - } - - free(data->hostname); - data->hostname = NULL; - - if (data->fd != -1) { - close(data->fd); - data->fd = -1; - } - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() done\n"); - free(data); -} -#endif - #ifndef _WIN32 /** * \internal Rozwiązuje nazwę serwera w osobnym procesie. @@ -873,24 +596,14 @@ } #if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT) -# ifdef _WIN32 - type = GG_RESOLVER_WIN32; -# else type = GG_RESOLVER_FORK; -# endif #else type = GG_RESOLVER_PTHREAD; #endif } switch (type) { -#ifdef _WIN32 - case GG_RESOLVER_WIN32: - gs->resolver_type = type; - gs->resolver_start = gg_resolve_win32thread; - gs->resolver_cleanup = gg_resolve_win32thread_cleanup; - return 0; -#else +#ifdef GG_CONFIG_HAVE_FORK case GG_RESOLVER_FORK: gs->resolver_type = type; gs->resolver_start = gg_resolver_fork_start; @@ -994,24 +707,14 @@ } #if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT) -# ifdef _WIN32 - type = GG_RESOLVER_WIN32; -# else type = GG_RESOLVER_FORK; -# endif #else type = GG_RESOLVER_PTHREAD; #endif } switch (type) { -#ifdef _WIN32 - case GG_RESOLVER_WIN32: - gh->resolver_type = type; - gh->resolver_start = gg_resolve_win32thread; - gh->resolver_cleanup = gg_resolve_win32thread_cleanup; - return 0; -#else +#ifdef GG_CONFIG_HAVE_FORK case GG_RESOLVER_FORK: gh->resolver_type = type; gh->resolver_start = gg_resolver_fork_start; @@ -1089,13 +792,7 @@ gg_global_resolver_cleanup = NULL; return 0; -#ifdef _WIN32 - case GG_RESOLVER_WIN32: - gg_global_resolver_type = type; - gg_global_resolver_start = gg_resolve_win32thread; - gg_global_resolver_cleanup = gg_resolve_win32thread_cleanup; - return 0; -#else +#ifdef GG_CONFIG_HAVE_FORK case GG_RESOLVER_FORK: gg_global_resolver_type = type; gg_global_resolver_start = gg_resolver_fork_start;