1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
/* www.c, liboop, copyright 1999 Dan Egnor
This is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License, version 2.1 or later.
See the file COPYING for details. */
#ifdef HAVE_WWW
/* Yecch: the libwww header files need this. */
#define HAVE_CONFIG_H
#undef PACKAGE
#undef VERSION
#include <stdarg.h> /* Needed for our cut-down libwww headers. */
#include "oop.h"
#include "HTEvent.h"
#include "HTMemory.h"
#include "oop-www.h"
#include <assert.h>
struct event {
HTEvent *event;
struct timeval time;
};
typedef struct event descriptor[HTEvent_TYPES];
static int num = 0,size = 0;
static descriptor *array = NULL;
static oop_source *oop = NULL;
static struct event *get_event(SOCKET sock,HTEventType type) {
assert(sock < size && "invalid file descriptor");
return &array[sock][HTEvent_INDEX(type)];
}
static void *on_time(oop_source *s,struct timeval tv,void *x) {
struct event *event;
SOCKET sock = (int) x;
int j;
for (j = 0; j < HTEvent_TYPES; ++j) {
event = &array[sock][j];
if (NULL != event->event && 0 <= event->event->millis
&& tv.tv_sec == event->time.tv_sec
&& tv.tv_usec == event->time.tv_usec)
break;
}
assert(j < HTEvent_TYPES);
event->event->cbf(sock,event->event->param,HTEvent_TIMEOUT);
return OOP_CONTINUE;
}
static void set_timer(struct event *event) {
if (0 <= event->event->millis) {
gettimeofday(&event->time,NULL);
event->time.tv_sec += event->event->millis / 1000;
event->time.tv_usec += event->event->millis % 1000;
if (event->time.tv_usec > 1000000) {
event->time.tv_usec -= 1000000;
++event->time.tv_sec;
}
oop->on_time(oop,event->time,on_time,event);
}
}
static void *on_fd(oop_source *s,int fd,oop_event type,void *x) {
HTEventType www_type;
struct event *event;
switch (type) {
case OOP_READ:
www_type = HTEvent_READ;
break;
case OOP_WRITE:
www_type = HTEvent_WRITE;
break;
default:
assert(0);
}
event = get_event(fd,www_type);
if (0 <= event->event->millis) {
oop->cancel_time(oop,event->time,on_time,event);
set_timer(event);
}
event->event->cbf(fd,event->event->param,www_type);
return OOP_CONTINUE;
}
static void dereg(SOCKET sock,HTEventType www_type,oop_event oop_type) {
struct event *event = get_event(sock,www_type);
assert(sock < size && "invalid file descriptor");
if (NULL != event->event) {
--num;
oop->cancel_fd(oop,sock,oop_type);
if (0 <= event->event->millis)
oop->cancel_time(oop,event->time,on_time,event);
event->event = NULL;
}
}
static int reg(SOCKET sock,HTEventType type,HTEvent *www_event) {
oop_event oop_type;
struct event *event;
switch (HTEvent_INDEX(type)) {
case HTEvent_INDEX(HTEvent_READ):
oop_type = OOP_READ;
break;
case HTEvent_INDEX(HTEvent_WRITE):
oop_type = OOP_WRITE;
break;
case HTEvent_INDEX(HTEvent_OOB):
/* XXX: we don't handle this; does anything use it? */
return HT_ERROR;
default:
assert(0 && "invalid HTEvent type specified");
}
if (sock >= size) {
int newsize = size ? (2*size) : 16;
descriptor *newarray = oop_malloc(sizeof(*newarray) * newsize);
int i,j;
if (NULL == newarray) return HT_ERROR;
memcpy(newarray,array,sizeof(*newarray) * size);
for (i = size; i < newsize; ++i)
for (j = 0; j < HTEvent_TYPES; ++j) {
newarray[i][j].event = NULL;
}
array = newarray;
size = newsize;
}
dereg(sock,type,oop_type);
event = get_event(sock,type);
event->event = www_event;
oop->on_fd(oop,sock,oop_type,on_fd,NULL);
set_timer(event);
++num;
return HT_OK;
}
static int unreg(SOCKET sock,HTEventType type) {
oop_event oop_type;
switch (HTEvent_INDEX(type)) {
case HTEvent_INDEX(HTEvent_READ):
oop_type = OOP_READ;
break;
case HTEvent_INDEX(HTEvent_WRITE):
oop_type = OOP_WRITE;
break;
case HTEvent_INDEX(HTEvent_OOB):
/* XXX: we don't handle this; does anything use it? */
return HT_ERROR;
default:
assert(0 && "invalid HTEvent type specified");
}
dereg(sock,type,oop_type);
return HT_OK;
}
void oop_www_register(oop_source *source) {
oop = source;
HTEvent_setRegisterCallback(reg);
HTEvent_setUnregisterCallback(unreg);
}
void oop_www_cancel() {
assert(0 == num && "cannot unregister with pending libwww events");
HTEvent_setRegisterCallback(NULL);
HTEvent_setUnregisterCallback(NULL);
oop = NULL;
}
void oop_www_memory() {
oop_malloc = HTMemory_malloc;
oop_realloc = HTMemory_realloc;
oop_free = HTMemory_free;
}
#endif
|