/************************************************************************
* IRC - Internet Relay Chat, src/fds.c
* Copyright (C) 2003 Lucas Madar
*
* fds.c -- file descriptor list management routines
*
*/
/* $Id: fds.c,v 1.3 2005/07/05 03:17:53 sheik Exp $ */
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "h.h"
#include "fds.h"
#include "numeric.h"
#include "memcount.h"
void engine_add_fd(int);
void engine_del_fd(int);
void engine_change_fd_state(int, unsigned int);
struct afd_entry {
int type;
void *value;
unsigned int flags;
void *internal;
};
struct afd_entry fd_list[MAXCONNECTIONS];
#ifdef DEBUGMODE
static char *type_string(int type)
{
switch(type)
{
case FDT_NONE:
return "NONE";
case FDT_CLIENT:
return "client";
case FDT_AUTH:
return "auth";
case FDT_RESOLVER:
return "resolver";
case FDT_LISTENER:
return "listener";
case FDT_CALLBACKP:
return "callback";
}
return "???";
}
static char *flags_string(unsigned int flags)
{
static char fbuf[512];
fbuf[0] = '\0';
if(flags & FDF_WANTREAD)
{
if(fbuf[0])
strcat(fbuf, ", ");
strcat(fbuf, "read");
}
if(flags & FDF_WANTWRITE)
{
if(fbuf[0])
strcat(fbuf, ", ");
strcat(fbuf, "write");
}
return fbuf;
}
void report_fds(aClient *cptr)
{
int i;
char *name, *blocking;
for(i = 0; i < MAXCONNECTIONS; i++)
{
if(fd_list[i].type == FDT_NONE)
continue;
if(fd_list[i].type == FDT_CLIENT ||
fd_list[i].type == FDT_AUTH)
{
aClient *cptr = (aClient *) fd_list[i].value;
int hide = (IsConnecting(cptr) || IsHandshake(cptr) || IsServer(cptr)) ? HIDEME : 0;
name = get_client_name(cptr, hide);
blocking = (cptr->flags & FLAGS_BLOCKED) ?
"BLOCKED" : "_";
}
else
{
name = "-";
blocking = "-";
}
sendto_one(cptr, ":%s %d %s :%d - %s [%s] %s %s",
me.name, RPL_STATSDEBUG, cptr->name,
i, type_string(fd_list[i].type),
flags_string(fd_list[i].flags),
name, blocking);
}
}
#endif
static inline void fd_range_assert(int fd)
{
if(fd < 0 || fd >= MAXCONNECTIONS)
abort();
}
static inline void fd_notused_assert(int fd)
{
if(fd_list[fd].type != FDT_NONE)
abort();
}
static inline void fd_used_assert(int fd)
{
if(fd_list[fd].type == FDT_NONE)
abort();
}
void add_fd(int fd, int type, void *value)
{
fdfprintf(stderr, "add_fd: %d %d %x\n", fd, type, (int) value);
fd_range_assert(fd);
fd_notused_assert(fd);
fd_list[fd].type = type;
fd_list[fd].value = value;
fd_list[fd].flags = 0;
engine_add_fd(fd);
}
void del_fd(int fd)
{
fdfprintf(stderr, "del_fd: %d\n", fd);
fd_range_assert(fd);
fd_used_assert(fd);
engine_del_fd(fd);
fd_list[fd].type = FDT_NONE;
fd_list[fd].value = NULL;
fd_list[fd].internal = NULL;
}
void set_fd_flags(int fd, unsigned int flags)
{
int oldflags;
fd_range_assert(fd);
fd_used_assert(fd);
oldflags = fd_list[fd].flags;
fd_list[fd].flags |= flags;
fdfprintf(stderr, "set_fd_flags: %d %x [%x -> %x]\n", fd, flags, oldflags, fd_list[fd].flags);
if(oldflags != fd_list[fd].flags)
engine_change_fd_state(fd, fd_list[fd].flags);
}
void unset_fd_flags(int fd, unsigned int flags)
{
int oldflags;
fd_range_assert(fd);
fd_used_assert(fd);
oldflags = fd_list[fd].flags;
fd_list[fd].flags &= ~(flags);
fdfprintf(stderr, "unset_fd_flags: %d %x [%x -> %x]\n", fd, flags, oldflags, fd_list[fd].flags);
if(oldflags != fd_list[fd].flags)
engine_change_fd_state(fd, fd_list[fd].flags);
}
void get_fd_info(int fd, int *type, unsigned int *flags, void **value)
{
fd_range_assert(fd);
*type = fd_list[fd].type;
*flags = fd_list[fd].flags;
*value = fd_list[fd].value;
}
unsigned int get_fd_flags(int fd)
{
fd_range_assert(fd);
fd_used_assert(fd);
return fd_list[fd].flags;
}
void init_fds()
{
memset(fd_list, 0, sizeof(struct afd_entry) * MAXCONNECTIONS);
}
void set_fd_internal(int fd, void *ptr)
{
fd_list[fd].internal = ptr;
}
void *get_fd_internal(int fd)
{
return fd_list[fd].internal;
}
/*
* check_client_fd
*
* called whenever a state change is necessary on a client
* ie, when ident and dns are finished
*/
void check_client_fd(aClient *cptr)
{
if (DoingAuth(cptr))
{
unsigned int fdflags = get_fd_flags(cptr->authfd);
if(!(fdflags & FDF_WANTREAD))
set_fd_flags(cptr->authfd, FDF_WANTREAD);
if((cptr->flags & FLAGS_WRAUTH) && !(fdflags & FDF_WANTWRITE))
set_fd_flags(cptr->authfd, FDF_WANTWRITE);
else if(!(cptr->flags & FLAGS_WRAUTH) && (fdflags & FDF_WANTWRITE))
unset_fd_flags(cptr->authfd, FDF_WANTWRITE);
return;
}
if (DoingDNS(cptr))
return;
set_fd_flags(cptr->fd, FDF_WANTREAD);
}
u_long
memcount_fds(MCfds *mc)
{
mc->file = __FILE__;
mc->s_fdlist.c = sizeof(fd_list)/sizeof(fd_list[0]);
mc->s_fdlist.m = sizeof(fd_list);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1