[963] in BarnOwl Developers
[D-O-H] r950 - trunk/owl
daemon@ATHENA.MIT.EDU (asedeno@MIT.EDU)
Thu Oct 29 18:11:37 2009
Resent-From: nelhage@mit.edu
Resent-To: barnowl-dev-mtg@charon.mit.edu
X-Original-To: nelhage@nelhage.com
To: dirty-owl-hackers@mit.edu
From: asedeno@MIT.EDU
Reply-to: dirty-owl-hackers@MIT.EDU
Date: Mon, 18 Feb 2008 20:54:45 -0500 (EST)
Author: asedeno
Date: 2008-02-18 20:54:45 -0500 (Mon, 18 Feb 2008)
New Revision: 950
Added:
trunk/owl/select.c
Log:
Merging in the select branch, part 2. select.c
Added: trunk/owl/select.c
===================================================================
--- trunk/owl/select.c (rev 0)
+++ trunk/owl/select.c 2008-02-19 01:54:45 UTC (rev 950)
@@ -0,0 +1,242 @@
+#include "owl.h"
+
+static const char fileIdent[] = "$Id: select.c 894 2008-01-17 07:13:44Z asedeno $";
+
+/* Returns the index of the dispatch for the file descriptor. */
+int owl_select_find_dispatch(int fd)
+{
+ int i, len;
+ owl_list *dl;
+ owl_dispatch *d;
+
+ dl = owl_global_get_dispatchlist(&g);
+ len = owl_list_get_size(dl);
+ for(i = 0; i < len; i++) {
+ d = (owl_dispatch*)owl_list_get_element(dl, i);
+ if (d->fd == fd) return i;
+ }
+ return -1;
+}
+
+/* Adds a new owl_dispatch to the list, replacing existing ones if needed. */
+void owl_select_add_dispatch(owl_dispatch *d)
+{
+ int elt;
+ owl_list *dl;
+
+ elt = owl_select_find_dispatch(d->fd);
+ dl = owl_global_get_dispatchlist(&g);
+
+ if (elt != -1) { /* If we have a dispatch for this FD */
+ owl_dispatch *d_old;
+ d_old = (owl_dispatch*)owl_list_get_element(dl, elt);
+ /* Ignore if we're adding the same dispatch again. Otherwise
+ replace the old dispatch. */
+ if (d_old != d) {
+ owl_list_replace_element(dl, elt, d);
+ owl_free(d_old);
+ }
+ }
+ else {
+ owl_list_append_element(dl, d);
+ }
+}
+
+/* Removes an owl_dispatch to the list, based on it's file descriptor. */
+void owl_select_remove_dispatch(int fd)
+{
+ int elt;
+ owl_list *dl;
+
+ elt = owl_select_find_dispatch(fd);
+ dl = owl_global_get_dispatchlist(&g);
+
+ if (elt != -1) {
+ owl_dispatch *d;
+ d = (owl_dispatch*)owl_list_get_element(dl, elt);
+ owl_list_remove_element(dl, elt);
+ if (d->pfunc) {
+ owl_perlconfig_dispatch_free(d);
+ }
+ owl_free(d);
+ }
+}
+
+int owl_select_dispatch_count()
+{
+ return owl_list_get_size(owl_global_get_dispatchlist(&g));
+}
+
+int owl_select_add_perl_dispatch(int fd, SV *cb)
+{
+ int elt;
+ owl_dispatch *d;
+ elt = owl_select_find_dispatch(fd);
+ if (elt != -1) {
+ d = (owl_dispatch*)owl_list_get_element(owl_global_get_dispatchlist(&g), elt);
+ if (d->pfunc == NULL) {
+ /* don't mess with non-perl dispatch functions from here. */
+ return 1;
+ }
+ }
+
+ d = malloc(sizeof(owl_dispatch));
+ d->fd = fd;
+ d->cfunc = NULL;
+ d->pfunc = cb;
+ owl_select_add_dispatch(d);
+ return 0;
+}
+
+int owl_select_remove_perl_dispatch(int fd)
+{
+ int elt;
+ owl_dispatch *d;
+
+ elt = owl_select_find_dispatch(fd);
+ if (elt != -1) {
+ d = (owl_dispatch*)owl_list_get_element(owl_global_get_dispatchlist(&g), elt);
+ if (d->pfunc != NULL) {
+ owl_select_remove_dispatch(fd);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int owl_select_dispatch_prepare_fd_sets(fd_set *r, fd_set *w, fd_set *e)
+{
+ int i, len, max_fd;
+ owl_dispatch *d;
+ owl_list *dl;
+
+ dl = owl_global_get_dispatchlist(&g);
+ FD_ZERO(r);
+ FD_ZERO(e);
+ max_fd = 0;
+ len = owl_select_dispatch_count(g);
+ for(i = 0; i < len; i++) {
+ d = (owl_dispatch*)owl_list_get_element(dl, i);
+ FD_SET(d->fd, r);
+ FD_SET(d->fd, w);
+ FD_SET(d->fd, e);
+ if (max_fd < d->fd) max_fd = d->fd;
+ }
+ return max_fd + 1;
+}
+
+void owl_select_dispatch(fd_set *fds, int max_fd)
+{
+ int i, len;
+ owl_dispatch *d;
+ owl_list *dl;
+
+ dl = owl_global_get_dispatchlist(&g);
+ len = owl_select_dispatch_count();
+ for(i = 0; i < len; i++) {
+ d = (owl_dispatch*)owl_list_get_element(dl, i);
+ /* While d shouldn't normally be null, the list may be altered by
+ * functions we dispatch to. */
+ if (d != NULL && FD_ISSET(d->fd, fds)) {
+ if (d->cfunc != NULL) {
+ (d->cfunc)();
+ }
+ else if (d->pfunc != NULL) {
+ owl_perlconfig_do_dispatch(d);
+ }
+ }
+ }
+}
+
+int owl_select_aim_hack(fd_set *fds)
+{
+ aim_conn_t *cur;
+ aim_session_t *sess;
+ int max_fd;
+
+ FD_ZERO(fds);
+ max_fd = 0;
+ sess = owl_global_get_aimsess(&g);
+ for (cur = sess->connlist, max_fd = 0; cur; cur = cur->next) {
+ if (cur->fd != -1) {
+ FD_SET(cur->fd, fds);
+ if (cur->fd > max_fd)
+ max_fd = cur->fd;
+ }
+ }
+ cur = owl_global_get_bosconn(&g);
+ if (cur->fd != -1) {
+ FD_SET(cur->fd, fds);
+ if (cur->fd > max_fd)
+ max_fd = cur->fd;
+ }
+
+ return max_fd;
+}
+
+void owl_select()
+{
+ int i, max_fd, aim_max_fd, aim_done;
+ fd_set r;
+ fd_set w;
+ fd_set e;
+ fd_set aim_fds;
+ struct timeval timeout;
+
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ max_fd = owl_select_dispatch_prepare_fd_sets(&r, &w, &e);
+
+ /* AIM HACK:
+ *
+ * The problem - I'm not sure where to hook into the owl/faim
+ * interface to keep track of when the AIM socket(s) open and
+ * close. In particular, the bosconn thing throws me off. So,
+ * rather than register particular dispatchers for AIM, I look up
+ * the relevant FDs and add them to select's watch lists, then
+ * check for them individually before moving on to the other
+ * dispatchers. --asedeno
+ */
+ aim_done = 1;
+ FD_ZERO(&aim_fds);
+ FD_ZERO(&w);
+ if (owl_global_is_doaimevents(&g)) {
+ aim_done = 0;
+ aim_max_fd = owl_select_aim_hack(&aim_fds);
+ if (max_fd < aim_max_fd) max_fd = aim_max_fd;
+ for(i = 0; i <= aim_max_fd; i++) {
+ if (FD_ISSET(i, &aim_fds)) {
+ FD_SET(i, &r);
+ FD_SET(i, &w); /* Yes, we're checking writable sockets
+ here. Without it, AIM login is really
+ slow. */
+ FD_SET(i, &e);
+ }
+ }
+ }
+ /* END AIM HACK */
+
+ if ( select(max_fd, &r, &w, &e, &timeout) ) {
+ /* Merge fd_sets and clear AIM FDs. */
+ for(i = 0; i <= max_fd; i++) {
+ /* Merge all interesting FDs into one set, since we have a
+ single dispatch per FD. */
+ if (FD_ISSET(i, &r) || FD_ISSET(i, &w) || FD_ISSET(i, &e)) {
+ /* AIM HACK: no separate dispatch, just process here if
+ needed, and only once per run through. */
+ if (!aim_done && FD_ISSET(i, &aim_fds)) {
+ owl_process_aim();
+ aim_done = 1;
+ }
+ else {
+ FD_SET(i, &r);
+ }
+ }
+ }
+
+ /* NOTE: the same dispatch function is called for both exceptional
+ and read ready FDs. */
+ owl_select_dispatch(&r, max_fd);
+ }
+}