changeset 9657:51464cbbdc1a

[gaim-migrate @ 10505] I fixed my bug from an hour ago, cleaned up a few more things, and separated the code for the dns lookup child into a function. You know, functions? The things that make code suck less? committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Wed, 04 Aug 2004 01:51:22 +0000
parents 2ea77e275b85
children 0b570eec4eca
files src/proxy.c
diffstat 1 files changed, 127 insertions(+), 117 deletions(-) [+]
line wrap: on
line diff
--- a/src/proxy.c	Wed Aug 04 00:43:53 2004 +0000
+++ b/src/proxy.c	Wed Aug 04 01:51:22 2004 +0000
@@ -417,6 +417,120 @@
 #endif
 }
 
+static void
+gaim_dns_childthread(int child_out, int child_in, dns_params_t *dns_params)
+{
+	const int zero = 0;
+	int rc;
+#if HAVE_GETADDRINFO
+	struct addrinfo hints, *res, *tmp;
+	char servname[20];
+#else
+	struct sockaddr_in sin;
+	const size_t addrlen = sizeof(sin);
+#endif
+
+#ifdef HAVE_SIGNAL_H
+	signal(SIGHUP, SIG_DFL);
+	signal(SIGINT, SIG_DFL);
+	signal(SIGQUIT, SIG_DFL);
+	signal(SIGCHLD, SIG_DFL);
+	signal(SIGTERM, SIG_DFL);
+	signal(SIGTRAP, trap_gdb_bug);
+#endif
+
+	while (1) {
+		if (dns_params->hostname[0] == '\0') {
+			const char Y = 'Y';
+			fd_set fds;
+			struct timeval tv = { .tv_sec = 40 , .tv_usec = 0 };
+			FD_ZERO(&fds);
+			FD_SET(child_in, &fds);
+			rc = select(child_in + 1, &fds, NULL, NULL, &tv);
+			if (!rc) {
+				if (opt_debug)
+					fprintf(stderr,"dns[%d]: nobody needs me... =(\n", getpid());
+				break;
+			}
+			rc = read(child_in, dns_params, sizeof(dns_params_t));
+			if (rc < 0) {
+				perror("read()");
+				break;
+			}
+			if (rc==0) {
+				if(opt_debug)
+					fprintf(stderr,"dns[%d]: Ops, father has gone, wait for me, wait...!\n", getpid());
+				_exit(0);
+			}
+			if (dns_params->hostname[0] == '\0') {
+				fprintf(stderr, "dns[%d]: hostname = \"\" (port = %d)!!!\n", getpid(), dns_params->port);
+				_exit(1);
+			}
+			write(child_out, &Y, 1);
+		}
+
+#if HAVE_GETADDRINFO
+		g_snprintf(servname, sizeof(servname), "%d", dns_params->port);
+		memset(&hints,0,sizeof(hints));
+
+		/* This is only used to convert a service
+		 * name to a port number. As we know we are
+		 * passing a number already, we know this
+		 * value will not be really used by the C
+		 * library.
+		 */
+		hints.ai_socktype = SOCK_STREAM;
+		rc = getaddrinfo(dns_params->hostname, servname, &hints, &res);
+		if(rc) {
+			write(child_out, &rc, sizeof(int));
+			close(child_out);
+			if(opt_debug)
+				fprintf(stderr,"dns[%d] Error: getaddrinfo returned %d\n",
+					getpid(), rc);
+			dns_params->hostname[0] = '\0';
+			continue;
+		}
+		write(child_out, &zero, sizeof(zero));
+		tmp = res;
+		while(res) {
+			size_t ai_addrlen = res->ai_addrlen;
+			write(child_out, &ai_addrlen, sizeof(ai_addrlen));
+			write(child_out, res->ai_addr, res->ai_addrlen);
+			res = res->ai_next;
+		}
+		freeaddrinfo(tmp);
+		write(child_out, &zero, sizeof(zero));
+#else
+		if (!inet_aton(hostname, &sin.sin_addr)) {
+			struct hostent *hp;
+			if(!(hp = gethostbyname(dns_params->hostname))) {
+				write(child_out, &h_errno, sizeof(int));
+				close(child_out);
+				if(opt_debug)
+					fprintf(stderr,"DNS Error: %d\n", h_errno);
+				_exit(0);
+			}
+			memset(&sin, 0, sizeof(struct sockaddr_in));
+			memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
+			sin.sin_family = hp->h_addrtype;
+		} else
+			sin.sin_family = AF_INET;
+
+		sin.sin_port = htons(dns_params->port);
+		write(child_out, &zero, sizeof(zero));
+		write(child_out, &addrlen, sizeof(addrlen));
+		write(child_out, &sin, addrlen);
+		write(child_out, &zero, sizeof(zero));
+#endif
+		dns_params->hostname[0] = '\0';
+	}
+
+	close(child_out);
+	close(child_in);
+
+	_exit(0);
+}
+
 int gaim_gethostbyname_async(const char *hostname, int port, dns_callback_t callback, gpointer data)
 {
 	pending_dns_request_t *req = NULL;
@@ -444,11 +558,10 @@
 			break;
 
 		req_free(req);
+		req = NULL;
 	}
 
-	/*
-	 * We need to create a new DNS request child.
-	 */
+	/* We need to create a new DNS request child */
 	if (req == NULL) {
 		int child_out[2], child_in[2];
 
@@ -467,144 +580,41 @@
 			return 0;
 		}
 
+		/* Create pipes for communicating with the child process */
 		if (pipe(child_out) || pipe(child_in)) {
 			gaim_debug(GAIM_DEBUG_ERROR, "dns",
 					   "Could not create pipes: %s\n", strerror(errno));
 			return -1;
 		}
 
-		/* We need to create a new child. */
-		req = g_new(pending_dns_request_t,1);
+		req = g_new(pending_dns_request_t, 1);
 
 		cope_with_gdb_brokenness();
 
+		/* Fork! */
 		req->dns_pid = fork();
 
-		/* If we are a child... */
-		if (req->dns_pid == 0) {
-			const int zero = 0;
-			int rc;
-
-#if HAVE_GETADDRINFO
-			struct addrinfo hints, *res, *tmp;
-			char servname[20];
-#else
-			struct sockaddr_in sin;
-			const size_t addrlen = sizeof(sin);
-#endif
-#ifdef HAVE_SIGNAL_H
-			signal(SIGHUP, SIG_DFL);
-			signal(SIGINT, SIG_DFL);
-			signal(SIGQUIT, SIG_DFL);
-			signal(SIGCHLD, SIG_DFL);
-			signal(SIGTERM, SIG_DFL);
-			signal(SIGTRAP, trap_gdb_bug);
-#endif
-
+		/* If we are the child process... */
+		if (req->dns_pid==0) {
 			/* We should not access the parent's side of the pipe, so close them... */
 			close(child_out[0]);
 			close(child_in[1]);
 
-			while (1) {
-				if (dns_params.hostname[0] == '\0') {
-					const char Y = 'Y';
-					fd_set fds;
-					struct timeval tv = { .tv_sec = 40 , .tv_usec = 0 };
-					FD_ZERO(&fds);
-					FD_SET(child_in[0], &fds);
-					rc = select(child_in[0]+1, &fds, NULL, NULL, &tv);
-					if (!rc) {
-						if (opt_debug)
-							fprintf(stderr,"dns[%d]: Nobody needs me... =(\n", getpid());
-						break;
-					}
-					rc = read(child_in[0], &dns_params, sizeof(dns_params));
-					if (rc < 0) {
-						perror("read()");
-						break;
-					}
-					if (rc==0) {
-						if (opt_debug)
-							fprintf(stderr,"dns[%d]: Father has gone, wait for me, wait...!\n", getpid());
-						_exit(0);
-					}
-					if (dns_params.hostname[0] == '\0') {
-						fprintf(stderr, "dns[%d]: Hostname = \"\" (port = %d)!!!\n", getpid(), dns_params.port);
-						_exit(1);
-					}
-					write(child_out[1], &Y, 1);
-				}
-
-#if HAVE_GETADDRINFO
-				g_snprintf(servname, sizeof(servname), "%d", dns_params.port);
-				memset(&hints,0,sizeof(hints));
-
-				/* This is only used to convert a service
-				 * name to a port number. As we know we are
-				 * passing a number already, we know this
-				 * value will not be really used by the C
-				 * library.
-				 */
-				hints.ai_socktype = SOCK_STREAM;
-				rc = getaddrinfo(dns_params.hostname, servname, &hints, &res);
-				if (rc) {
-					write(child_out[1], &rc, sizeof(int));
-					close(child_out[1]);
-					if (opt_debug)
-						fprintf(stderr,"dns[%d] Error: getaddrinfo returned %d\n",
-							getpid(), rc);
-					dns_params.hostname[0] = '\0';
-					continue;
-				}
-				write(child_out[1], &zero, sizeof(zero));
-				tmp = res;
-				while (res) {
-					size_t ai_addrlen = res->ai_addrlen;
-					write(child_out[1], &ai_addrlen, sizeof(ai_addrlen));
-					write(child_out[1], res->ai_addr, res->ai_addrlen);
-					res = res->ai_next;
-				}
-				freeaddrinfo(tmp);
-				write(child_out[1], &zero, sizeof(zero));
-#else
-				/* XXX - Should hostname be changed to dns_params.hostname? */
-				if (!inet_aton(hostname, &sin.sin_addr)) {
-					struct hostent *hp;
-					if (!(hp = gethostbyname(dns_params.hostname))) {
-						write(child_out[1], &h_errno, sizeof(int));
-						close(child_out[1]);
-						if (opt_debug)
-							fprintf(stderr,"DNS Error: %d\n", h_errno);
-						_exit(0);
-					}
-					memset(&sin, 0, sizeof(struct sockaddr_in));
-					memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
-					sin.sin_family = hp->h_addrtype;
-				} else
-					sin.sin_family = AF_INET;
-				sin.sin_port = htons(dns_params.port);
-				write(child_out[1], &zero, sizeof(zero));
-				write(child_out[1], &addrlen, sizeof(addrlen));
-				write(child_out[1], &sin, addrlen);
-				write(child_out[1], &zero, sizeof(zero));
-#endif
-				dns_params.hostname[0] = '\0';
-			}
-			close(child_out[1]);
-			close(child_in[0]);
-			_exit(0);
-		} /* End of child process */
+			gaim_dns_childthread(child_out[1], child_in[0], &dns_params);
+			/* The thread calls _exit() rather than returning, so we never get here */
+		}
 
 		/* We should not access the child's side of the pipe, so close them... */
 		close(child_out[1]);
 		close(child_in[0]);
-		if (req->dns_pid==-1) {
+		if (req->dns_pid == -1) {
 			gaim_debug(GAIM_DEBUG_ERROR, "dns",
 					   "Could not create child process for DNS: %s\n",
 					   strerror(errno));
 			g_free(req);
 			return -1;
 		}
+
 		req->fd_out = child_out[0];
 		req->fd_in = child_in[1];
 		number_of_dns_children++;
@@ -613,7 +623,7 @@
 				   req->dns_pid, number_of_dns_children);
 	}
 
-	req->host = g_strdup(dns_params.hostname);
+	req->host = g_strdup(hostname);
 	req->port = port;
 	req->callback = callback;
 	req->data = data;