Commit Diff


commit - 4db29b007689d34adeaca8cbe8676f7c2aedc2ab
commit + 5b2364b236ce3027ff5fcf93cad8cb75034d3838
blob - ebfee022305c28b10b764427089e48f465987878
blob + bdef8dd2469f823120ff2f868d86a87472e23c45
--- ChangeLog
+++ ChangeLog
@@ -11,7 +11,7 @@
 
 
 ngIRCd CVSHEAD
-
+  - Internal: Simplified resolver code.
   - Fixed a bug that caused the daemon to leak file descriptors when no
     resolver subprocesses could be created.
   - JOIN now supports more than one channel key at a time.
@@ -641,4 +641,4 @@ ngIRCd 0.0.1, 31.12.2001
 
 
 -- 
-$Id: ChangeLog,v 1.294 2005/09/02 22:12:43 alex Exp $
+$Id: ChangeLog,v 1.295 2005/09/12 19:10:20 fw Exp $
blob - 8f04a1bb4534160fa16a0d26b224ba248f907f00
blob + 57bfb16854d39b26aba0b00e9c8dda9567eaeafe
--- src/ngircd/conn.c
+++ src/ngircd/conn.c
@@ -17,7 +17,7 @@
 #include "portab.h"
 #include "io.h"
 
-static char UNUSED id[] = "$Id: conn.c,v 1.180 2005/09/11 11:42:48 fw Exp $";
+static char UNUSED id[] = "$Id: conn.c,v 1.181 2005/09/12 19:10:20 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -105,6 +105,7 @@ int deny_severity = LOG_ERR;
 
 static void server_login PARAMS((CONN_ID idx));
 
+static void cb_Read_Resolver_Result PARAMS(( int sock, UNUSED short what));
 static void cb_clientserver PARAMS((int sock, short what));
 
 static void
@@ -198,22 +199,6 @@ cb_clientserver(int sock, short what)
 }
 
 
-static void
-FreeRes_stat( CONNECTION *c )
-{
-	assert( c != NULL );
-	assert( c->res_stat != NULL );
-
-	if (!c->res_stat) return;
-
-	io_close( c->res_stat->pipe[0] );
-
-	array_free(&c->res_stat->buffer);
-	free( c->res_stat );
-	c->res_stat = NULL;
-}
-
-
 GLOBAL void
 Conn_Init( void )
 {
@@ -525,7 +510,7 @@ Conn_Handler( void )
 			if ( My_Connections[i].sock <= NONE )
 				continue;
 
-			if ( My_Connections[i].res_stat ) {
+			if (Resolve_INPROGRESS(&My_Connections[i].res_stat)) {
 				/* wait for completion of Resolver Sub-Process */
 				io_event_del( My_Connections[i].sock, IO_WANTREAD );
 				continue;
@@ -789,9 +774,10 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, b
 		Log( LOG_INFO, "Connection %d with %s:%d closed (in: %.1fk, out: %.1fk).", Idx, My_Connections[Idx].host, ntohs( My_Connections[Idx].addr.sin_port ), in_k, out_k );
 	}
 
-	/* Is there a resolver sub-process running? */
-	if( My_Connections[Idx].res_stat )
-		FreeRes_stat( &My_Connections[Idx] );
+	/* cancel running resolver */
+	if (Resolve_INPROGRESS(&My_Connections[Idx].res_stat)) {
+		Resolve_Shutdown(&My_Connections[Idx].res_stat);
+	}
 
 	/* Servers: Modify time of next connect attempt? */
 	Conf_UnsetServer( Idx );
@@ -864,6 +850,7 @@ Handle_Write( CONN_ID Idx )
 #endif
 		return false;
 	}
+	assert( My_Connections[Idx].sock > NONE );
 
 #ifdef DEBUG
 	Log(LOG_DEBUG, "Handle_Write() called for connection %d ...", Idx);
@@ -921,7 +908,6 @@ New_Connection( int Sock )
 #endif
 	struct sockaddr_in new_addr;
 	int new_sock, new_sock_len;
-	RES_STAT *s;
 	CONN_ID idx;
 	CLIENT *c;
 	POINTER *ptr;
@@ -1044,14 +1030,10 @@ New_Connection( int Sock )
 	/* Hostnamen ermitteln */
 	strlcpy( My_Connections[idx].host, inet_ntoa( new_addr.sin_addr ), sizeof( My_Connections[idx].host ));
 	Client_SetHostname( c, My_Connections[idx].host );
-#ifdef IDENTAUTH
-	s = Resolve_Addr( &new_addr, My_Connections[idx].sock );
-#else
-	s = Resolve_Addr( &new_addr );
-#endif
-	/* resolver process has been started */
-	if( s ) My_Connections[idx].res_stat = s;
-
+
+	Resolve_Addr(&My_Connections[idx].res_stat, &new_addr,
+		My_Connections[idx].sock, cb_Read_Resolver_Result);
+
 	/* Penalty-Zeit setzen */
 	Conn_SetPenalty( idx, 4 );
 	return new_sock;
@@ -1335,7 +1317,6 @@ Check_Servers( void )
 {
 	/* Check if we can establish further server links */
 
-	RES_STAT *s;
 	CONN_ID idx;
 	int i, n;
 
@@ -1344,7 +1325,8 @@ Check_Servers( void )
 		if( My_Connections[idx].sock != SERVER_WAIT ) continue;
 
 		/* IP resolved? */
-		if( My_Connections[idx].res_stat == NULL ) New_Server( Conf_GetServer( idx ), idx );
+		if (Resolve_SUCCESS(&My_Connections[idx].res_stat))
+			New_Server(Conf_GetServer( idx ), idx);
 	}
 
 	/* Check all configured servers */
@@ -1383,7 +1365,6 @@ Check_Servers( void )
 		Log( LOG_DEBUG, "Preparing connection %d for \"%s\" ...", idx, Conf_Server[i].host );
 #endif
 
-		/* Verbindungs-Struktur initialisieren */
 		Init_Conn_Struct( idx );
 		My_Connections[idx].sock = SERVER_WAIT;
 		Conf_Server[i].conn_id = idx;
@@ -1391,10 +1372,10 @@ Check_Servers( void )
 		/* Resolve Hostname. If this fails, try to use it as an IP address */
 		strlcpy( Conf_Server[i].ip, Conf_Server[i].host, sizeof( Conf_Server[i].ip ));
 		strlcpy( My_Connections[idx].host, Conf_Server[i].host, sizeof( My_Connections[idx].host ));
-		s = Resolve_Name( Conf_Server[i].host );
 
-		/* resolver process running? */
-		if( s ) My_Connections[idx].res_stat = s;
+		assert(Resolve_Getfd(&My_Connections[idx].res_stat) < 0);
+
+		Resolve_Name(&My_Connections[idx].res_stat, Conf_Server[i].host, cb_Read_Resolver_Result);
 	}
 } /* Check_Servers */
 
@@ -1412,15 +1393,6 @@ New_Server( int Server, CONN_ID Idx )
 	assert( Server > NONE );
 	assert( Idx > NONE );
 
-	/* Did we get a valid IP address? */
-	if( ! Conf_Server[Server].ip[0] ) {
-		/* No. Free connection structure and abort: */
-		Log( LOG_ERR, "Can't connect to \"%s\": ip address unknown!", Conf_Server[Server].host );
-        	Init_Conn_Struct( Idx );
-	        Conf_Server[Server].conn_id = NONE;
-		return;
-	}
-
 	Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ", Conf_Server[Server].host,
 							Conf_Server[Server].ip, Conf_Server[Server].port );
 
@@ -1504,6 +1476,7 @@ Init_Conn_Struct( CONN_ID Idx )
 	My_Connections[Idx].sock = NONE;
 	My_Connections[Idx].lastdata = now;
 	My_Connections[Idx].lastprivmsg = now;
+	Resolve_Init(&My_Connections[Idx].res_stat);
 } /* Init_Conn_Struct */
 
 
@@ -1545,27 +1518,31 @@ Init_Socket( int Sock )
 } /* Init_Socket */
 
 
-GLOBAL
-void Read_Resolver_Result( int r_fd )
+static void
+cb_Read_Resolver_Result( int r_fd, UNUSED short events )
 {
 	/* Read result of resolver sub-process from pipe and update the
 	 * apropriate connection/client structure(s): hostname and/or
 	 * IDENT user name.*/
 
 	CLIENT *c;
-	int bytes_read, i, n;
-	unsigned int len;
-	RES_STAT *s;
-	char *ptr;
-	char *bufptr;
-	char readbuf[HOST_LEN];
+	int i, n;
+	size_t len;
+	char *identptr;
+#ifdef IDENTAUTH
+	char readbuf[HOST_LEN + 2 + CLIENT_USER_LEN];
+#else
+	char readbuf[HOST_LEN + 1];
+#endif
 
-	Log( LOG_DEBUG, "Resolver: started, fd %d", r_fd );
+#ifdef DEBUG
+	Log( LOG_DEBUG, "Resolver: Got callback on fd %d, events %d", r_fd, events );
+#endif
+
 	/* Search associated connection ... */
 	for( i = 0; i < Pool_Size; i++ ) {
 		if(( My_Connections[i].sock != NONE )
-		  && ( My_Connections[i].res_stat != NULL )
-		  && ( My_Connections[i].res_stat->pipe[0] == r_fd ))
+		  && ( Resolve_Getfd(&My_Connections[i].res_stat) == r_fd ))
 			break;
 	}
 	if( i >= Pool_Size ) {
@@ -1573,99 +1550,54 @@ void Read_Resolver_Result( int r_fd )
 		 * been closed!? We'll ignore that ... */
 		io_close( r_fd );
 #ifdef DEBUG
-		Log( LOG_DEBUG, "Resolver: Got result for unknown connection!?" );
+		Log( LOG_DEBUG, "Resolver: Got callback for unknown connection!?" );
 #endif
 		return;
 	}
 
-	/* Get resolver structure */
-	s = My_Connections[i].res_stat;
-	assert( s != NULL );
-
 	/* Read result from pipe */
-	bytes_read = read( r_fd, readbuf, sizeof readbuf -1 );
-	if( bytes_read < 0 ) {
-		/* Error! */
-		Log( LOG_CRIT, "Resolver: Can't read result: %s!", strerror( errno ));
-		FreeRes_stat( &My_Connections[i] );
+	len = Resolve_Read(&My_Connections[i].res_stat, readbuf, sizeof readbuf -1);
+	if (len == 0) 
 		return;
-	}
-	len = (unsigned int) bytes_read;
+
 	readbuf[len] = '\0';
-	if (!array_catb(&s->buffer, readbuf, len)) {
-		Log( LOG_CRIT, "Resolver: Can't append result %s to buffer: %s", readbuf, strerror( errno ));
-		FreeRes_stat(&My_Connections[i]);
+	identptr = strchr(readbuf, '\n');
+	assert(identptr != NULL);
+	if (!identptr) {
+		Log( LOG_CRIT, "Resolver: Got malformed result!");
 		return;
 	}
 
-	if (!array_cat0_temporary(&s->buffer)) {
-		Log( LOG_CRIT, "Resolver: Can't append result %s to buffer: %s", readbuf, strerror( errno ));
-		FreeRes_stat(&My_Connections[i]);
-		return;
-	}
-
-	/* If the result string is incomplete, return to main loop and
-	 * wait until we can read in more bytes. */
-#ifdef IDENTAUTH
-try_resolve:
-#endif
-	bufptr = (char*) array_start(&s->buffer);
-	assert(bufptr != NULL);
-	ptr = strchr( bufptr, '\n' );
-	if( ! ptr ) return;
-	*ptr = '\0';
-
+	*identptr = '\0';
 #ifdef DEBUG
-	Log( LOG_DEBUG, "Got result from resolver: \"%s\" (%u bytes read), stage %d.", bufptr, len, s->stage);
+	Log( LOG_DEBUG, "Got result from resolver: \"%s\" (%u bytes read).", readbuf, len);
 #endif
-
 	/* Okay, we got a complete result: this is a host name for outgoing
-	 * connections and a host name or IDENT user name (if enabled) for
+	 * connections and a host name and IDENT user name (if enabled) for
 	 * incoming connections.*/
-	if( My_Connections[i].sock > NONE )
-	{
+	if( My_Connections[i].sock > NONE ) {
 		/* Incoming connection. Search client ... */
 		c = Client_GetFromConn( i );
 		assert( c != NULL );
 
 		/* Only update client information of unregistered clients */
-		if( Client_Type( c ) == CLIENT_UNKNOWN )
-		{
-			switch(s->stage) {
-				case 0: /* host name */
-				strlcpy( My_Connections[i].host, bufptr, sizeof( My_Connections[i].host));
-
-				Client_SetHostname( c, bufptr);
+		if( Client_Type( c ) == CLIENT_UNKNOWN ) {
+			strlcpy(My_Connections[i].host, readbuf, sizeof( My_Connections[i].host));
+			Client_SetHostname( c, readbuf);
 #ifdef IDENTAUTH
-				/* clean up buffer for IDENT result */
-				len = strlen(bufptr) + 1;
-				assert(len <= array_bytes(&s->buffer));
-				array_moveleft(&s->buffer, 1, len);
-
-				/* Don't close pipe and clean up, but
-				 * instead wait for IDENT result */
-				s->stage = 1;
-				goto try_resolve;
-
-				case 1: /* IDENT user name */
-				if (array_bytes(&s->buffer)) {
-					bufptr = (char*) array_start(&s->buffer);
-					Log( LOG_INFO, "IDENT lookup for connection %ld: \"%s\".", i, bufptr);
-					Client_SetUser( c, bufptr, true );
-				}
-				else Log( LOG_INFO, "IDENT lookup for connection %ld: no result.", i );
-#endif
-				break;
-				default:
-				Log( LOG_ERR, "Resolver: got result for unknown stage %d!?", s->stage );
+			++identptr;
+			if (*identptr) {
+				Log( LOG_INFO, "IDENT lookup for connection %ld: \"%s\".", i, identptr);
+				Client_SetUser( c, identptr, true );
+			} else {
+				Log( LOG_INFO, "IDENT lookup for connection %ld: no result.", i );
 			}
+#endif
 		}
 #ifdef DEBUG
 		else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i );
 #endif
-	}
-	else
-	{
+	} else {
 		/* Outgoing connection (server link): set the IP address
 		 * so that we can connect to it in the main loop. */
 
@@ -1673,16 +1605,12 @@ try_resolve:
 		n = Conf_GetServer( i );
 		assert( n > NONE );
 
-		bufptr = (char*) array_start(&s->buffer);
-		strlcpy( Conf_Server[n].ip, bufptr, sizeof( Conf_Server[n].ip ));
+		strlcpy( Conf_Server[n].ip, readbuf, sizeof( Conf_Server[n].ip ));
 	}
 
-	/* Clean up ... */
-	FreeRes_stat( &My_Connections[i] );
-
 	/* Reset penalty time */
 	Conn_ResetPenalty( i );
-} /* Read_Resolver_Result */
+} /* cb_Read_Resolver_Result */
 
 
 static void
blob - d9c81a8cb259724716bea94c2a693a3b3e543c7a
blob + 307e5bb53931554dce04fa326e1617956b4b8bc9
--- src/ngircd/conn.h
+++ src/ngircd/conn.h
@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: conn.h,v 1.38 2005/07/30 22:53:16 alex Exp $
+ * $Id: conn.h,v 1.39 2005/09/12 19:10:20 fw Exp $
  *
  * Connection management (header)
  */
@@ -54,7 +54,7 @@ typedef struct _Connection
 {
 	int sock;			/* Socket handle */
 	struct sockaddr_in addr;	/* Client address */
-	RES_STAT *res_stat;		/* Status of resolver process, if any */
+	RES_STAT res_stat;		/* Status of resolver process */
 	char host[HOST_LEN];		/* Hostname */
 	array rbuf;			/* Read buffer */
 	array wbuf;			/* Write buffer */
@@ -93,11 +93,8 @@ GLOBAL void Conn_Close PARAMS(( CONN_ID Idx, char *Log
 
 GLOBAL void Conn_SyncServerStruct PARAMS(( void ));
 
-GLOBAL void Read_Resolver_Result PARAMS(( int x ));
-
 GLOBAL int Conn_MaxFD;
 
-
 #endif
 
 
blob - 4a6f2e14dce2fc3e8a7e2781ee0bb75fdaa10953
blob + e25849497f06869065b02082bc294689b2a808c0
--- src/ngircd/resolve.c
+++ src/ngircd/resolve.c
@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: resolve.c,v 1.20 2005/09/11 11:42:48 fw Exp $";
+static char UNUSED id[] = "$Id: resolve.c,v 1.21 2005/09/12 19:10:20 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -42,140 +42,106 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.20 2005/
 #include "io.h"
 
 
-#ifdef IDENTAUTH
 static void Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, int Sock, int w_fd ));
-#else
-static void Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, int w_fd ));
-#endif
+static void Do_ResolveName PARAMS(( const char *Host, int w_fd ));
+static bool register_callback PARAMS((RES_STAT *s, void (*cbfunc)(int, short)));
 
-static void Do_ResolveName PARAMS(( char *Host, int w_fd ));
-
 #ifdef h_errno
 static char *Get_Error PARAMS(( int H_Error ));
 #endif
 
-static RES_STAT *New_Res_Stat PARAMS(( void ));
+static int
+Resolver_fork(int *pipefds)
+{
+	int pid;
+	if (pipe(pipefds) != 0) {
+                Log( LOG_ALERT, "Resolver: Can't create output pipe: %s!", strerror( errno ));
+                return -1;
+	}
 
-
-static void
-cb_resolver(int fd, short unused) {
-	(void) unused;	/* shut up compiler warning */
-	Read_Resolver_Result(fd);
+	pid = fork();
+	switch(pid) {
+		case -1:
+			Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno ));
+			close(pipefds[0]);
+			close(pipefds[1]);
+			return -1;
+		case 0: /* child */
+			close(pipefds[0]);
+			Log_Init_Resolver( );
+			return 0;
+	}
+	/* parent */
+	close(pipefds[1]);
+	return pid; 
 }
 
 
-#ifdef IDENTAUTH
-GLOBAL RES_STAT *
-Resolve_Addr( struct sockaddr_in *Addr, int Sock )
-#else
-GLOBAL RES_STAT *
-Resolve_Addr( struct sockaddr_in *Addr )
-#endif
+GLOBAL bool
+Resolve_Addr( RES_STAT *s, struct sockaddr_in *Addr, int identsock, void (*cbfunc)(int, short))
 {
-	/* Resolve IP (asynchronous!). On errors, e.g. if the child process
-	 * can't be forked, this functions returns NULL. */
+	/* Resolve IP (asynchronous!). */
+	int pid, pipefd[2];
+	assert(s != NULL);
+	s->success = false;
 
-	RES_STAT *s;
-	int pid;
-
-	s = New_Res_Stat( );
-	if( ! s ) return NULL;
-
-	/* For sub-process */
-	pid = fork( );
+	pid = Resolver_fork(pipefd);
 	if (pid > 0) {
-		close( s->pipe[1] );
-		/* Main process */
+#ifdef DEBUG
 		Log( LOG_DEBUG, "Resolver for %s created (PID %d).", inet_ntoa( Addr->sin_addr ), pid );
-		if (!io_setnonblock( s->pipe[0] )) {
-			Log( LOG_DEBUG, "Could not set Non-Blocking mode for pipefd %d", s->pipe[0] );
-			goto out;
-		}
-		if (!io_event_create( s->pipe[0], IO_WANTREAD, cb_resolver )) {
-			Log( LOG_DEBUG, "Could not add pipefd %dto event watchlist: %s",
-								s->pipe[0], strerror(errno) );
-			goto out;
-		}
+#endif
 		s->pid = pid;
-		return s;
+		s->resolver_fd = pipefd[0];
+		return register_callback(s, cbfunc);
 	} else if( pid == 0 ) {
-		close( s->pipe[0] );
 		/* Sub process */
-		Log_Init_Resolver( );
-#ifdef IDENTAUTH
-		Do_ResolveAddr( Addr, Sock, s->pipe[1] );
-#else
-		Do_ResolveAddr( Addr, s->pipe[1] );
-#endif
+		Do_ResolveAddr( Addr, identsock, pipefd[1]);
 		Log_Exit_Resolver( );
 		exit(0);
 	}
-	
-	Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno ));
-
-out: /* Error! */
-	close( s->pipe[0] );
-	close( s->pipe[1] );
-	free( s );
-return NULL;
+	return false;
 } /* Resolve_Addr */
 
 
-GLOBAL RES_STAT *
-Resolve_Name( char *Host )
+GLOBAL bool
+Resolve_Name( RES_STAT *s, const char *Host, void (*cbfunc)(int, short))
 {
-	/* Resolve hostname (asynchronous!). On errors, e.g. if the child
-	 * process can't be forked, this functions returns NULL. */
+	/* Resolve hostname (asynchronous!). */
+	int pid, pipefd[2];
+	assert(s != NULL);
+	s->success = false;
 
-	RES_STAT *s;
-	int pid;
-
-	s = New_Res_Stat( );
-	if( ! s ) return NULL;
-
-	/* Fork sub-process */
-	pid = fork( );
+	pid = Resolver_fork(pipefd);
 	if (pid > 0) {
-		close( s->pipe[1] );
 		/* Main process */
+#ifdef DEBUG
 		Log( LOG_DEBUG, "Resolver for \"%s\" created (PID %d).", Host, pid );
-		if (!io_setnonblock( s->pipe[0] )) {
-			Log( LOG_DEBUG, "Could not set Non-Blocking mode for pipefd %d", s->pipe[0] );
-			goto out;
-		}
-		if (!io_event_create( s->pipe[0], IO_WANTREAD, cb_resolver )) {
-			Log( LOG_DEBUG, "Could not add pipefd %dto event watchlist: %s",
-								s->pipe[0], strerror(errno) );
-			goto out;
-		}
+#endif
 		s->pid = pid;
-		return s;
+		s->resolver_fd = pipefd[0];
+		return register_callback(s, cbfunc);
 	} else if( pid == 0 ) {
-		close( s->pipe[0] );
 		/* Sub process */
-		Log_Init_Resolver( );
-		Do_ResolveName( Host, s->pipe[1] );
+		Do_ResolveName(Host, pipefd[1]);
 		Log_Exit_Resolver( );
 		exit(0);
 	}
-
-	Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno ));
-
-out: /* Error! */
-	close( s->pipe[0] );
-	close( s->pipe[1] );
-	free( s );
-	return NULL;
+	return false;
 } /* Resolve_Name */
 
 
-#ifdef IDENTAUTH
-static void
-Do_ResolveAddr( struct sockaddr_in *Addr, int Sock, int w_fd )
-#else
+GLOBAL void
+Resolve_Init(RES_STAT *s)
+{
+	assert(s != NULL);
+	s->resolver_fd = -1;
+	s->pid = 0;
+	/* s->success must not be changed -- it will be set by other Resolve_*() functions */
+}
+
+
 static void
-Do_ResolveAddr( struct sockaddr_in *Addr, int w_fd )
-#endif
+Do_ResolveAddr( struct sockaddr_in *Addr, int identsock, int w_fd )
 {
 	/* Resolver sub-process: resolve IP address and write result into
 	 * pipe to parent. */
@@ -190,9 +156,7 @@ Do_ResolveAddr( struct sockaddr_in *Addr, int w_fd )
 #ifdef IDENTAUTH
 	char *res;
 #endif
-
 	array_init(&resolved_addr);
-
 	/* Resolve IP address */
 #ifdef DEBUG
 	Log_Resolver( LOG_DEBUG, "Now resolving %s ...", inet_ntoa( Addr->sin_addr ));
@@ -236,25 +200,26 @@ Do_ResolveAddr( struct sockaddr_in *Addr, int w_fd )
 	}
 
 #ifdef IDENTAUTH
-	/* Do "IDENT" (aka "AUTH") lookup and append result to resolved_addr array */
-	Log_Resolver( LOG_DEBUG, "Doing IDENT lookup on socket %d ...", Sock );
-	res = ident_id( Sock, 10 );
-	Log_Resolver( LOG_DEBUG, "Ok, IDENT lookup on socket %d done: \"%s\"", Sock, res ? res : "" );
-
-	if (res) {
-		if (!array_cats(&resolved_addr, res))
+	assert(identsock >= 0);
+	if (identsock >= 0) {
+		/* Do "IDENT" (aka "AUTH") lookup and append result to resolved_addr array */
+#ifdef DEBUG
+		Log_Resolver( LOG_DEBUG, "Doing IDENT lookup on socket %d ...", identsock );
+#endif
+		res = ident_id( identsock, 10 );
+#ifdef DEBUG
+		Log_Resolver(LOG_DEBUG, "Ok, IDENT lookup on socket %d done: \"%s\"",
+							identsock, res ? res : "(NULL)" );
+#endif
+		if (res && !array_cats(&resolved_addr, res)) {
 			Log_Resolver(LOG_WARNING, "Resolver: Cannot copy IDENT result: %s!", strerror(errno));
-		/* try to omit ident and return hostname only */ 
-	}
+			/* omit ident and return hostname only */ 
+		}
 
-	if (!array_catb(&resolved_addr, "\n", 1)) {
-		close(w_fd);
-		Log_Resolver(LOG_CRIT, "Resolver: Cannot copy result: %s!", strerror(errno));
-		array_free(&resolved_addr);
-		return;
+		if (res) free(res);
 	}
-
-	if (res) free(res);
+#else
+	(void)identsock;
 #endif
 	len = array_bytes(&resolved_addr);
 	if( (size_t)write( w_fd, array_start(&resolved_addr), len) != len )
@@ -266,7 +231,7 @@ Do_ResolveAddr( struct sockaddr_in *Addr, int w_fd )
 
 
 static void
-Do_ResolveName( char *Host, int w_fd )
+Do_ResolveName( const char *Host, int w_fd )
 {
 	/* Resolver sub-process: resolve name and write result into pipe
 	 * to parent. */
@@ -289,10 +254,12 @@ Do_ResolveName( char *Host, int w_fd )
 #else
 		Log_Resolver( LOG_WARNING, "Can't resolve \"%s\"!", Host );
 #endif
-		ip[0] = '\0';
+		close(w_fd);
+		return;
 	}
-	if( ip[0] ) Log_Resolver( LOG_DEBUG, "Ok, translated \"%s\" to %s.", Host, ip );
-
+#ifdef DEBUG
+	Log_Resolver( LOG_DEBUG, "Ok, translated \"%s\" to %s.", Host, ip );
+#endif
 	/* Write result into pipe to parent */
 	len = strlen( ip );
 	ip[len] = '\n'; len++;
@@ -328,33 +295,70 @@ Get_Error( int H_Error )
 #endif
 
 
-static RES_STAT *
-New_Res_Stat( void )
+static bool
+register_callback( RES_STAT *s, void (*cbfunc)(int, short))
 {
-	RES_STAT *s;
+	assert(cbfunc);
+	assert(s != NULL);
+	assert(s->resolver_fd >= 0);
 
-	/* Allocate memory */
-	s = (RES_STAT *)malloc( sizeof( RES_STAT ));
-	if( ! s )
-	{
-		Log( LOG_EMERG, "Resolver: Can't allocate memory! [Resolve_Addr]" );
-		return NULL;
-	}
+	if (io_setnonblock(s->resolver_fd) &&
+		io_event_create(s->resolver_fd, IO_WANTREAD, cbfunc))
+			return true;
 
-	/* Initialize pipe for result */
-	if( pipe( s->pipe ) != 0 )
-	{
-		free( s );
-		Log( LOG_ALERT, "Resolver: Can't create output pipe: %s!", strerror( errno ));
-		return NULL;
-	}
+	Log( LOG_CRIT, "Resolver: Could not register callback function: %s!", strerror(errno));
+	Resolve_Shutdown(s);
+	return false;
+}
 
-	s->stage = 0;
-	array_init(&s->buffer);
-	s->pid = -1;
 
-	return s;
-} /* New_Res_Stat */
+GLOBAL bool
+Resolve_Shutdown( RES_STAT *s)
+{
+	bool ret = false;
 
+	assert(s != NULL);
+	assert(s->resolver_fd >= 0);
 
+	if (s->resolver_fd >= 0)
+		ret = io_close(s->resolver_fd);
+
+	Resolve_Init(s);
+	return ret;
+}
+
+                
+GLOBAL size_t
+Resolve_Read( RES_STAT *s, void* readbuf, size_t buflen)
+{
+	/* Read result of resolver sub-process from pipe */
+	int err, bytes_read;
+	assert(buflen > 0);
+
+	/* Read result from pipe */
+	errno = 0;
+	bytes_read = read(s->resolver_fd, readbuf, buflen);
+	if (bytes_read < 0) {
+		if (errno != EAGAIN) {
+			err = errno;
+			Log( LOG_CRIT, "Resolver: Can't read result: %s!", strerror(err));
+			Resolve_Shutdown(s);
+			errno = err;
+			return 0;
+		}
+		return 0;
+	}
+
+	Resolve_Shutdown(s);
+	if (bytes_read == 0) {	/* EOF: lookup failed */
+#ifdef DEBUG
+		Log( LOG_DEBUG, "Resolver: Can't read result: EOF");
+#endif
+		return 0;
+	}
+
+	s->success = true;
+	return bytes_read;
+}
 /* -eof- */
+
blob - 0791229123b47acf8833e466ceef3a57707b7b42
blob + 030356886c6f28d2c8280d251343ea2fb3a3e055
--- src/ngircd/resolve.h
+++ src/ngircd/resolve.h
@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: resolve.h,v 1.10 2005/09/11 11:42:48 fw Exp $
+ * $Id: resolve.h,v 1.11 2005/09/12 19:10:21 fw Exp $
  *
  * Asynchronous resolver (header)
  */
@@ -18,31 +18,25 @@
 #define __resolve_h__
 
 #include "array.h"
-
-#ifdef HAVE_SYS_SELECT_H
-#	include <sys/select.h>
-#endif
-#include <sys/types.h>
 #include <netinet/in.h>
 
-
-typedef struct _Res_Stat
-{
+/* This struct must not be accessed directly */
+typedef struct _Res_Stat {
 	int pid;			/* PID of resolver process */
-	int pipe[2];			/* pipe for lookup result */
-	int stage;			/* Hostname/IP(0) or IDENT(1)? */
-	array buffer;			/* resolved hostname / ident result */
+	int resolver_fd;		/* pipe fd for lookup result. */
+	bool success;			/* resolver returned data */
 } RES_STAT;
 
 
-#ifdef IDENTAUTH
-GLOBAL RES_STAT *Resolve_Addr PARAMS(( struct sockaddr_in *Addr, int Sock ));
-#else
-GLOBAL RES_STAT *Resolve_Addr PARAMS(( struct sockaddr_in *Addr ));
-#endif
+#define Resolve_Getfd(x)		((x)->resolver_fd)
+#define Resolve_INPROGRESS(x)		((x)->resolver_fd >= 0)
+#define Resolve_SUCCESS(x)		((x)->resolver_fd < 0 && (x)->success)
 
-GLOBAL RES_STAT *Resolve_Name PARAMS(( char *Host ));
+GLOBAL bool Resolve_Addr PARAMS(( RES_STAT *s, struct sockaddr_in *Addr, int identsock, void (*cbfunc)(int, short)));
+GLOBAL bool Resolve_Name PARAMS(( RES_STAT *s, const char *Host, void (*cbfunc)(int, short) ));
+GLOBAL size_t Resolve_Read PARAMS(( RES_STAT *s, void *buf, size_t buflen));
+GLOBAL void Resolve_Init PARAMS(( RES_STAT *s));
+GLOBAL bool Resolve_Shutdown PARAMS(( RES_STAT *s));
 
-
 #endif
 /* -eof- */