commit - 4db29b007689d34adeaca8cbe8676f7c2aedc2ab
commit + 5b2364b236ce3027ff5fcf93cad8cb75034d3838
blob - ebfee022305c28b10b764427089e48f465987878
blob + bdef8dd2469f823120ff2f868d86a87472e23c45
--- ChangeLog
+++ ChangeLog
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.
--
-$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
#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>
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
}
-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 )
{
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;
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 );
#endif
return false;
}
+ assert( My_Connections[Idx].sock > NONE );
#ifdef DEBUG
Log(LOG_DEBUG, "Handle_Write() called for connection %d ...", Idx);
#endif
struct sockaddr_in new_addr;
int new_sock, new_sock_len;
- RES_STAT *s;
CONN_ID idx;
CLIENT *c;
POINTER *ptr;
/* 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;
{
/* Check if we can establish further server links */
- RES_STAT *s;
CONN_ID idx;
int i, n;
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 */
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;
/* 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 */
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 );
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 */
} /* 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 ) {
* 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. */
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
* (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)
*/
{
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 */
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
#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>
#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. */
#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 ));
}
#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 )
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. */
#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++;
#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
* (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)
*/
#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- */