/****************************************************************************
* Copyright (C) 1998 WIDE Project. All rights reserved.
* Copyright (C) 1999,2000,2001,2002 University of Tromso. All rights reserved.
* Copyright (C) 2002 Invenia Innovation AS. All rights reserved.
*
* Author: Feike W. Dillema, feico@pasta.cs.uit.no.
* based on newbie code by Yusuke DOI, Keio Univ. Murai Lab.
****************************************************************************/
/*
* <$Id: ev_tcp.c,v 3.7 2002/03/04 12:34:10 dillema Exp $>
*/
#include "totd.h"
/* TCP event lists */
static G_List *ConnL_head;
static G_List *ETOL_head;
/*
* TCP service handling
*/
int ev_tcp_srv_accept (int srv_sock) {
struct sockaddr_storage peer;
unsigned int peer_len;
int conn_sock;
if (T.debug > 2)
syslog (LOG_DEBUG, "ev_tcp_srv_accept(): sock = %d", srv_sock);
peer_len = sizeof (struct sockaddr_storage);
conn_sock = accept (srv_sock, (struct sockaddr *)&peer, &peer_len);
if (conn_sock < 0) {
syslog (LOG_ERR, "accept: %m");
return -1;
}
return tcp_response_start (conn_sock, (struct sockaddr *)&peer);
}
/*
* Generic TCP event handling routines
*/
int ev_tcp_common_eq (void *arg1, void *arg2) {
Ev_TCP_Common_Data *etcd_arg1;
Ev_TCP_Common_Data *etcd_arg2;
etcd_arg1 = arg1;
etcd_arg2 = arg2;
if (etcd_arg1->sock == etcd_arg2->sock)
return 0;
else
return 1;
}
G_List *ev_tcp_common_init (void) {
G_List *gl;
gl = list_init ();
if (!gl)
return NULL;
gl->list_data = NULL;
return gl;
}
int ev_tcp_common_register (G_List *gl, int sock, Context *cptr) {
const char *fn = "ev_tcp_common_register()";
Ev_TCP_Common_Data *etcd_new;
if (T.debug > 2)
syslog (LOG_DEBUG, "%s: sock = %d", fn, sock);
etcd_new = malloc (sizeof (Ev_TCP_Common_Data));
if (!etcd_new)
return -1;
etcd_new->sock = sock;
etcd_new->cptr = cptr;
if (list_add (gl, etcd_new) < 0)
return -1;
return 0;
}
int ev_tcp_common_remove (G_List *gl, int sock) {
const char *fn = "ev_tcp_common_remove()";
Ev_TCP_Common_Data etcd_tmp;
Ev_TCP_Common_Data *etcd_p;
G_List *gl_tmp;
if (T.debug > 2)
syslog (LOG_DEBUG, "%s: sock = %d", fn, sock);
etcd_tmp.sock = sock;
etcd_tmp.cptr = NULL;
gl_tmp = list_search (gl, (void *) &etcd_tmp, ev_tcp_common_eq);
if (!gl_tmp)
return -1;
etcd_p = (Ev_TCP_Common_Data *) list_delete (gl_tmp);
free (etcd_p);
return 0;
}
int ev_tcp_common_fds (G_List *gl, fd_set *fds) {
Ev_TCP_Common_Data *etcd_p;
G_List *gl_tmp;
int maxid = 0;
gl->list_data = NULL;
for (gl_tmp = gl->next; gl_tmp->list_data; gl_tmp = gl_tmp->next) {
etcd_p = ((Ev_TCP_Common_Data *) (gl_tmp->list_data));
if (T.debug > 2)
syslog (LOG_DEBUG, "ev_tcp_common_fds: FD_SET(%d)",
etcd_p->sock);
FD_SET (etcd_p->sock, fds);
maxid = MAXNUM (etcd_p->sock, maxid);
}
return maxid;
}
int ev_tcp_common_fd_check (G_List *gl, fd_set *fds) {
G_List *gl_tmp;
Context *cont;
Ev_TCP_Common_Data *etcd_p;
int s_tmp;
for (gl_tmp = gl->next; gl_tmp->list_data; gl_tmp = gl_tmp->next) {
etcd_p = (Ev_TCP_Common_Data *) (gl_tmp->list_data);
s_tmp = etcd_p->sock;
if (FD_ISSET (s_tmp, fds)) {
FD_CLR (s_tmp, fds);
/*
* etcd_p MAY be released within context, so keep
* context alone
*/
cont = etcd_p->cptr;
/* resume context */
return cont->process (cont);
}
}
return 0;
}
/*
* TCP incoming connection event list
*/
int ev_tcp_conn_in_init (void) {
if (ConnL_head)
return -1;
ConnL_head = ev_tcp_common_init ();
if (!ConnL_head)
return -1;
return 0;
}
void ev_tcp_conn_in_finish (void) {
list_destroy (ConnL_head, free);
}
int ev_tcp_conn_in_register (int sock, Context *cptr) {
if (T.debug > 3)
syslog (LOG_DEBUG, "ev_tcp_conn_in_register(): start");
return ev_tcp_common_register (ConnL_head, sock, cptr);
}
int ev_tcp_conn_in_remove (int sock) {
if (T.debug > 3)
syslog (LOG_DEBUG, "ev_tcp_conn_in_remove(): start");
return ev_tcp_common_remove (ConnL_head, sock);
}
int ev_tcp_conn_in_fds (fd_set *fds) {
if (T.debug > 3)
syslog (LOG_DEBUG, "ev_tcp_conn_in_fds(): start");
return ev_tcp_common_fds (ConnL_head, fds);
}
int ev_tcp_conn_in_fd_check (fd_set *fds) {
if (T.debug > 3)
syslog (LOG_DEBUG, "ev_tcp_conn_in_fd_check(): start");
return ev_tcp_common_fd_check (ConnL_head, fds);
}
/*
* TCP outgoing connection event list
*/
int ev_tcp_out_init (void) {
if (ETOL_head)
return -1;
ETOL_head = ev_tcp_common_init ();
if (!ETOL_head)
return -1;
return 0;
}
void ev_tcp_out_finish (void) {
list_destroy (ETOL_head, free);
}
int ev_tcp_out_register (int sock, Context * cptr) {
if (T.debug > 3)
syslog (LOG_DEBUG, "ev_tcp_out_register(): start");
return ev_tcp_common_register (ETOL_head, sock, cptr);
}
int ev_tcp_out_remove (int sock) {
if (T.debug > 3)
syslog (LOG_DEBUG, "ev_tcp_out_remove(): start");
return ev_tcp_common_remove (ETOL_head, sock);
}
int ev_tcp_out_fds (fd_set * fds) {
if (T.debug > 3)
syslog (LOG_DEBUG, "ev_tcp_out_fds(): start");
return ev_tcp_common_fds (ETOL_head, fds);
}
int ev_tcp_out_fd_check (fd_set * fds) {
if (T.debug > 3)
syslog (LOG_DEBUG, "ev_tcp_out_fd_check(): start");
return ev_tcp_common_fd_check (ETOL_head, fds);
}
syntax highlighted by Code2HTML, v. 0.9.1