Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Sun, 7 Jan 2001 04:00:27 +0000 (04:00 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Sun, 7 Jan 2001 04:00:27 +0000 (04:00 +0000)
Log message:

Beginning to rough in how the event model will work...

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@363 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

include/ircd_network.h [new file with mode: 0644]
ircd/ircd_network.c [new file with mode: 0644]

diff --git a/include/ircd_network.h b/include/ircd_network.h
new file mode 100644 (file)
index 0000000..d220b6c
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef INCLUDED_ircd_network_h
+#define INCLUDED_ircd_network_h
+/*
+ * IRC - Internet Relay Chat, include/ircd_network.h
+ * Copyright (C) 2001 Kevin L. Mitchell <klmitch@mit.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef INCLUDED_config_h
+#include "config.h"
+#endif
+#ifndef INCLUDED_time_h
+#include <time.h>      /* struct timespec */
+#define INCLUDED_time_h
+#endif
+
+#ifndef HAVE_STRUCT_TIMESPEC
+struct timespec {
+  long int tv_sec;     /* seconds */
+  long int tv_nsec;    /* nanoseconds */
+};
+#endif /* !HAVE_STRUCT_TIMESPEC */
+
+typedef void (*EventCallBack)(struct Event*);
+
+enum SocketState {
+  SS_CONNECTING,       /* Connection in progress on socket */
+  SS_LISTENING,                /* Socket is a listening socket */
+  SS_CONNECTED,                /* Socket is a connected socket */
+  SS_DATAGRAM,         /* Socket is a datagram socket */
+  SS_CONNECTDG         /* Socket is a connected datagram socket */
+};
+
+enum TimerType {
+  TT_ABSOLUTE,         /* timer that runs at a specific time */
+  TT_RELATIVE,         /* timer that runs so many seconds in the future */
+  TT_PERIODIC          /* timer that runs periodically */
+};
+
+enum EventType {
+  ET_READ,             /* Readable event detected */
+  ET_WRITE,            /* Writable event detected */
+  ET_ACCEPT,           /* Connection can be accepted */
+  ET_CONNECT,          /* Connection completed */
+  ET_EOF,              /* End-of-file on connection */
+  ET_ERROR,            /* Error condition detected */
+  ET_SIGNAL,           /* A signal was received */
+  ET_TIMER             /* A timer expired */
+};
+
+struct Socket {
+  struct Socket*   s_next;     /* linked list of sockets */
+  struct Socket**  s_prev_p;
+  enum SocketState s_state;    /* state socket's in */
+  unsigned int    s_flags;     /* socket flags */
+  int             s_fd;        /* file descriptor for socket */
+  EventCallBack           s_callback;  /* single callback for socket */
+  void*                   s_data;      /* data for socket--struct Client, etc. */
+};
+
+#define SOCK_EVENT_READABLE    0x0001  /* interested in readable */
+#define SOCK_EVENT_WRITABLE    0x0002  /* interested in writable */
+#define SOCK_FLAG_CLOSED       0x0010  /* socket got closed at some point */
+
+struct Signal {
+  struct Signal*  sig_next;    /* linked list of signals */
+  struct Signal** sig_prev_p;
+  int            sig_signal;   /* signal number */
+  unsigned int   sig_count;    /* count of number of signals */
+  EventCallBack          sig_callback; /* signal callback function */
+  void*                  sig_data;     /* data for signal */
+};
+
+struct Timer {
+  struct Timer*   t_next;      /* linked list of timers */
+  struct Timer**  t_prev_p;
+  enum TimerType  t_type;      /* what type of timer this is */
+  struct timespec t_value;     /* value timer was added with */
+  struct timespec t_expire;    /* time at which timer expires */
+  EventCallBack          t_callback;   /* timer callback function */
+  void*                  t_data;       /* data for timer--struct Auth, whatever */
+};
+
+struct Event {
+  struct Event*           ev_next;     /* linked list of events on queue */
+  struct Event**   ev_prev_p;
+  enum EventType   ev_type;    /* Event type */
+  EventCallBack           ev_callback; /* Event callback function */
+  union {
+    struct Socket* gen_socket; /* Socket generating event */
+    struct Signal* gen_signal; /* signal generating event */
+    struct Timer*  gen_timer;  /* Timer generating event */
+  }               ev_gen;      /* object generating event */
+};
+
+void event_generate(enum EventType type, void* gen);
+
+#endif /* INCLUDED_ircd_network_h */
diff --git a/ircd/ircd_network.c b/ircd/ircd_network.c
new file mode 100644 (file)
index 0000000..746bc1a
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * IRC - Internet Relay Chat, ircd/gline.c
+ * Copyright (C) 2001 Kevin L. Mitchell <klmitch@mit.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+#include "ircd_network.h"
+
+#include "ircd_alloc.h"
+
+static struct {
+  struct Socket* sockets_head;
+  unsigned int  sockets_count;
+
+  struct Timer*         timers_head;
+  unsigned int  timers_count;
+
+  struct Signal* signals_head;
+  unsigned int  signals_count;
+
+  struct Event*         events_head;
+  struct Event*         events_tail;
+  unsigned int  events_count;
+
+  struct Event*         events_free;
+  unsigned int  events_alloc;
+} netInfo = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+/* Execute an event; optimizations should inline this */
+static void
+event_execute(struct Event* event)
+{
+  assert(0 == event->ev_prev_p); /* must be off queue first */
+
+  (*event->ev_callback)(event); /* execute the event */
+
+  event->ev_type = ET_ERROR; /* clear event data */
+  event->ev_callback = 0;
+  event->ev_gen.gen_socket = 0;
+
+  event->ev_next = netInfo.events_free; /* add to free list */
+  netInfo.events_free = event;
+}
+
+#ifndef IRCD_THREADED
+/* we synchronously execute the event when not threaded */
+#define event_add(event)       event_execute(event)
+
+#else
+/* add an event to the work queue */
+static void
+event_add(struct Event* event)
+{
+  /* This is just a placeholder; don't expect ircd to be threaded soon */
+  event->ev_next = 0; /* add event to end of event queue */
+  if (netInfo.events_head) {
+    assert(0 != netInfo.events_tail);
+
+    event->ev_prev_p = &netInfo.events_tail->ev_next;
+    netInfo.events_tail->ev_next = event;
+    netInfo.events_tail = event;
+  } else { /* queue was empty... */
+    assert(0 == netInfo.events_tail);
+
+    event->ev_prev_p = &netInfo.events_head;
+    netInfo.events_head = event;
+    netInfo.events_tail = event;
+  }
+
+  netInfo.events_count++; /* update count of pending events */
+
+  /* We'd also have to signal the work crew here */
+}
+#endif /* IRCD_THREADED */
+
+/* Generate an event and add it to the queue (or execute it) */
+void
+event_generate(enum EventType type, void* gen)
+{
+  struct Event* ptr;
+
+  assert(0 != gen);
+
+  if ((ptr = netInfo.events_free))
+    netInfo.events_free = ptr->next; /* pop one off the freelist */
+  else { /* allocate another structure */
+    ptr = (struct Event*) MyMalloc(sizeof(struct Event));
+    netInfo.events_alloc++; /* count of allocated events */
+  }
+
+  ptr->ev_type = type; /* Record event type */
+
+  switch (type) { /* link to generator properly */
+  case ET_READ: case ET_WRITE: case ET_ACCEPT: case ET_EOF: case ET_ERROR:
+    /* event is for a socket */
+    ptr->ev_gen.gen_socket = (struct Socket*) gen;
+    ptr->ev_callback = ptr->ev_gen.gen_socket->s_callback;
+    break;
+
+  case ET_SIGNAL: /* event is for a signal */
+    ptr->ev_gen.gen_signal = (struct Signal*) gen;
+    ptr->ev_callback = ptr->ev_gen.gen_signal->sig_callback;
+    break;
+
+  case ET_TIMER: /* event is for a timer */
+    ptr->ev_gen.gen_timer = (struct Timer*) gen;
+    ptr->ev_callback = ptr->ev_gen.gen_timer->t_callback;
+    break;
+  }
+
+  event_add(ptr); /* add event to queue */
+}