This patch is generated from the eventio branch of HEAD in squid Wed Sep 29 01:32:37 2004 GMT See http://devel.squid-cache.org/ Index: squid/configure.in diff -u squid/configure.in:1.36 squid/configure.in:1.17.8.8 --- squid/configure.in:1.36 Wed Nov 21 15:49:04 2001 +++ squid/configure.in Wed Nov 21 18:40:27 2001 @@ -719,16 +719,20 @@ ]) AC_ARG_ENABLE(ident-lookups, -[ --disable-ident-lookups - This allows you to remove code that performs +[ --enable-ident-lookups + This allows you to reenable code that performs Ident (RFC 931) lookups.], -[ if test "$enableval" = "no" ; then - echo "Disabling Ident Lookups" - AC_DEFINE(USE_IDENT, 0) +[ if test "$enableval" = "yes" ; then + echo "Enabling Ident Lookups" + use_ident="yes" else - AC_DEFINE(USE_IDENT, 1) + echo "Disabling Ident Lookups" + use_ident= fi ]) +if test "$use_dnsserver" = "yes"; then + AC_DEFINE(USE_IDENT) +fi AM_CONDITIONAL(USE_DNSSERVER, false) use_dnsserver= Index: squid/doc/debug-sections.txt diff -u squid/doc/debug-sections.txt:1.3 squid/doc/debug-sections.txt:1.3.14.1 --- squid/doc/debug-sections.txt:1.3 Sun Jan 7 15:53:36 2001 +++ squid/doc/debug-sections.txt Fri Feb 16 07:01:02 2001 @@ -86,3 +86,4 @@ section 79 HTTP Meter Header section 80 WCCP section 81 Store Removal/Replacement policy +section 90 New comm code Index: squid/doc/Programming-Guide/prog-guide.sgml diff -u squid/doc/Programming-Guide/prog-guide.sgml:1.16 squid/doc/Programming-Guide/prog-guide.sgml:1.9.8.13 --- squid/doc/Programming-Guide/prog-guide.sgml:1.16 Fri Sep 7 16:55:49 2001 +++ squid/doc/Programming-Guide/prog-guide.sgml Sat Feb 23 08:22:17 2002 @@ -3085,4 +3085,371 @@ that pointer was last accessed. If there is a leak, then the bug occurs somewhere after that point of the code. +Network I/O + +

+ The networking I/O layer is responsible for all network I/O (duh!). + +

+ It is implemented as a set of asyncronous operations for opening / + acception connections and reading/writing data on those connections. + The asyncronous operation means that each API call will only initiate + the operation, and when the operation s finished a supplied callback + function will be called. + +

+ Created filehandles are cbdata enabled, and any links / pointers to + filehandles should be properly managed as cbdata. + +

+ The return value of is 0 on success or -1 on error. On error, errno + will be set to a suitable error code. + +

+ All data is contained in IOBuf handlers. Each IOBuf has a reference + count, knows the amount of data stored in the IOBuf, actual size + of the allocated buffer area (internal) and the buffer area itself. + IOBuf is not a simple pointer. + +API + +

+ This are the functions available for performing network I/O operations + +ncomm_close + +

+ int + ncomm_close(filehandle *fh); + + +

+ Signals EOF on the socket. No further ncomm_write calls is allowed + after this. + +

+ Any pending I/O operations will be completed. + +

+ The socket will get fully closed when the last reference to the + filehandle is gone. + +ncomm_closed + +

+ int + ncomm_closed(filehandle *fh); + + +

+ Returns true if a filehandle has been closed with ncomm_close() + +ncomm_abort + +

+ int + ncomm_abort(filehandle *fh); + + +

+ Aborts the given network connection immediately. Any pending I/O + requests will be aborted. No callbacks will be done for + cancelled I/O requests. + +ncomm_listen + +

+ filehandle * + ncomm_listen(int sock_type, int proto, struct sockaddr *where, + int addrsize, int backlog, COMMNEWCB *callback, + void *cbdata) + + +

+ start listening for new connections on the given address/port. + +

+ The listening port is open until closed with ncomm_close or aborted + with ncomm_abort. comm_abort will cancel any pending queued incoming + connections not yet notified to the callback, while ncomm_close will + only stop listening for new connection requests. + +ncomm_accept + +

+ filehandle * + ncomm_accept(int sock_type, int proto, struct sockaddr *where, + struct sockaddr *from, int addrsize, + COMMNEWCB callback, void *cbdata) + + +

+ Accept a single connection from the given source + +

+ The returned filehandle is not valid for use until the callback + has been notified, except for comm_abort to cancel the connection + request. + +ncomm_connect + +

+ filehandle * + ncomm_connect(int sock_type, int proto, + const struct sockaddr *local, + const struct sockaddr *remote, int addrsize, + COMMNEWCB *callback, void *cbdata) + + +

+ Creates a new network connection to the given remote address, + optionally using a specified local source address. + +

+ The returned filehandle is not valid for use until the callback + has been notified, except for comm_abort to cancel the connection + request. + +ncomm_read + +

+ void + ncomm_read(filehandle *fh, COMMIOCB *callback, void *cbdata); + void + ncomm_read_limited(filehandle *fh, size_t max_size, COMMIOCB *callback, + void *cbdata); + + +

+ Request to write data. The callback will be called when + the request has finished, or if an unrecoverable error + occurs. + +

+ ncomm_read_limited can limit the max amount of data read in + one request. + +

+ Any errors will be signalled to the callback function. + +ncomm_write + +

+ void + ncomm_write(filehandle *fh, IOBUF *buf, COMMIOCB *callback, + void *cbdata); + + +

+ Request to write data. The callback will be called when + the request has finished, or if an unrecoverable error + occurs. + +

+ it is allowable to queue more write requests before the first has + finished. The requests will be processed and completed in the order + requested without reordering in data or callback order. + +

+ Any errors will be signalled to the callback function. + +ncomm_write_fragment + +

+ void + ncomm_write_fragment(filehandle *fh, IOBUF *buf, off_t offset, + size_t size, COMMIOCB *callback, void *cbdata); + + +

+ as ncomm_write, but only writes the indicated range of the supplied + IOBuf. + +ncomm_write_mbuf + +

+ void + ncomm_write_mbuf(filehandle *fh, MemBuf mb, COMMIOCB *callback, + void *cbdata); + + +

+ Like comm_write, but gets the data from a MemBuf instead of a IOBuf. + +

+ The MemBuf should not be used after this. The responsibility for + the data area is taken over by ncomm. + +ncomm_add_close_handler + +

+ int + ncomm_add_close_handler(filehandle *fh, COMMCLOSECB *handler, + void *cbdata); + + +

+ Registers a close handler what will be called when the socket is closed. + For example to clean up associated data structures or keep relations + proper. + +callbacks + +

+ Callbacks are used to get notifications when an network operation + has finished. These functions are passed as arguments to the + I/O operation to be performed, and will get called when the operation + finishes (completed or error). + +COMMNEWCB + +

+ typedef void + COMMNEWCB(filehandle *fh, int error, struct sockaddr *local, + struct sockaddr *peer, int addrsize, void *cbdata); + + +

+ Called when a new filehandle is created (ncomm_listen / ncomm_accept + / ncomm_connect) + +

+ On error, error is set to the appropriate errno. + +COMMIOCB + +

+ typedef void + COMMIOCB(filehandle *fh, IOBUF *buf, int offset, int size, + int errno, void *cbdata); + + +

+ Called when an I/O operation has finished (ncomm_read / + ncomm_write). + +

+ On error errno will be set to the error, otherwise errno will + be 0. + +

+ offset is the offset in the IOBUF where the data for the operation + starts, and size is the amount of data processed by the operation. + +

+ Note: On error the operation might have been partially completed. In + such case size >= 0 and errno != 0. + +COMMCLOSECB + +

+ typedef void + COMMCLOSECB(filehandle *fh, void *cbdata); + + +

+ Called when the filehandle is closed (ncomm_close / ncomm_abort), as + requested (ncomm_add_close_handler) + +"system" API + +

+ These functions are part of the general framework, and are generally + only called once, at suitable locations in the program. + +ncomm_handle_events + +

+ void + ncomm_handle_events(int timeout); + + +

+ This is the network I/O "main loop". Will execute any pending I/O + events, and if no events are pending optionally wait for timeout + milliseconds for an event to arrive. + +ncomm_module_init + +

+ void + ncomm_module_init(void); + + +

+ Initializes the network I/O subsystem + +ncomm_module_shutdown + +

+ void + ncomm_module_shutdown(void); + + +

+ Called on shutdown. Terminates all pending I/O operations and/or + connections and other related cleanups. + +ncomm_abort_all_connections + +

+ void + ncomm_abort_all_connections(void); + + +

+ Aborts all currently open network connections. + +Internal "poll" API + +

+ The "poll" API can be used on UNIX to implement event notification + mechanisms without having to reimplement all the read/write logics. + The purpose of this "event" system is to notify the generic + read/write logics when I/O is possible on a socket. + +comm_register_for_read_event + +

+ void + comm_register_for_read_event(filehandle *fh, COMMEVENTREAD *handler); + + +

+ Ask to receive read events on the filehandle "fh". When there is a + read event available, "handler" will be called. + +COMMEVENTREAD + +

+ typedef int COMMEVENTREAD(filehandle *fh); + + +

+ Callback function type for receiving read event notifications + +comm_register_for_write_event + +

+ void + comm_register_for_write_event(filehandle *fh, COMMEVENTWRITE *handler); + + +

+ Ask to receive write events on the filehandle "fh". When writing is + possible, "handler" will get called. + +COMMEVENTWRITE + +

+ typedef int COMMEVENTWRITE(filehandle *fh); + + +

+ Callback function type for receiving write event notifications + Index: squid/src/HttpBody.c diff -u squid/src/HttpBody.c:1.4 squid/src/HttpBody.c:1.4.12.1 --- squid/src/HttpBody.c:1.4 Fri Jan 12 00:20:32 2001 +++ squid/src/HttpBody.c Sat Feb 24 04:52:42 2001 @@ -64,7 +64,7 @@ { assert(body && p); if (body->mb.size) - packerAppend(p, body->mb.buf, body->mb.size); + packerAppend(p, *body->mb.bufp, body->mb.size); } #if UNUSED_CODE Index: squid/src/HttpHeader.c diff -u squid/src/HttpHeader.c:1.10 squid/src/HttpHeader.c:1.5.12.3 --- squid/src/HttpHeader.c:1.10 Wed Oct 24 02:42:11 2001 +++ squid/src/HttpHeader.c Sat Nov 17 05:11:57 2001 @@ -721,7 +721,7 @@ packerToMemInit(&p, &mb); httpHdrCcPackInto(cc, &p); /* put */ - httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_CACHE_CONTROL, NULL, mb.buf)); + httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_CACHE_CONTROL, NULL, *mb.bufp)); /* cleanup */ packerClean(&p); memBufClean(&mb); @@ -740,7 +740,7 @@ packerToMemInit(&p, &mb); httpHdrContRangePackInto(cr, &p); /* put */ - httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_CONTENT_RANGE, NULL, mb.buf)); + httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_CONTENT_RANGE, NULL, *mb.bufp)); /* cleanup */ packerClean(&p); memBufClean(&mb); @@ -759,7 +759,7 @@ packerToMemInit(&p, &mb); httpHdrRangePackInto(range, &p); /* put */ - httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_RANGE, NULL, mb.buf)); + httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_RANGE, NULL, *mb.bufp)); /* cleanup */ packerClean(&p); memBufClean(&mb); Index: squid/src/HttpHeaderTools.c diff -u squid/src/HttpHeaderTools.c:1.7 squid/src/HttpHeaderTools.c:1.6.8.2 --- squid/src/HttpHeaderTools.c:1.7 Thu Sep 6 14:19:46 2001 +++ squid/src/HttpHeaderTools.c Wed Sep 12 13:34:24 2001 @@ -131,7 +131,7 @@ MemBuf mb; memBufDefInit(&mb); memBufVPrintf(&mb, fmt, vargs); - httpHeaderPutStr(hdr, id, mb.buf); + httpHeaderPutStr(hdr, id, *mb.bufp); memBufClean(&mb); } Index: squid/src/Makefile.am diff -u squid/src/Makefile.am:1.8 squid/src/Makefile.am:1.4.4.3 --- squid/src/Makefile.am:1.8 Thu Nov 15 23:28:20 2001 +++ squid/src/Makefile.am Sat Nov 17 05:11:57 2001 @@ -116,6 +116,7 @@ $(DELAY_POOL_SOURCE) \ disk.c \ $(DNSSOURCE) \ + dlink.c \ enums.h \ errorpage.c \ ETag.c \ @@ -155,6 +156,8 @@ MemBuf.c \ mime.c \ multicast.c \ + ncomm.c \ + ncomm_poll.c \ neighbors.c \ net_db.c \ Packer.c \ @@ -195,6 +198,7 @@ wais.c \ wccp.c \ whois.c \ + wordlist.c \ $(WIN32SOURCE) nodist_squid_SOURCES = \ @@ -205,6 +209,26 @@ globals.c \ string_arrays.c +#NOBJS = \ +# cbdata.o \ +# client_side.o \ +# debug.o \ +# dlink.o \ +# fd.o \ +# globals.o \ +# MemBuf.o \ +# mem.o \ +# MemPool.o \ +# ncomm.o \ +# ncomm_poll.o \ +# ncomm_test.o \ +# string_arrays.o \ +# wordlist.o \ +# +#ncomm_test: $(NOBJS) +# $(CC) -o $@ $(LDFLAGS) $(NOBJS) $(SQUID_LIBS) + + squid_LDADD = \ -L../lib \ @XTRA_OBJS@ \ Index: squid/src/MemBuf.c diff -u squid/src/MemBuf.c:1.5 squid/src/MemBuf.c:1.4.12.3 --- squid/src/MemBuf.c:1.5 Fri Apr 20 14:27:11 2001 +++ squid/src/MemBuf.c Sun Feb 25 12:45:55 2001 @@ -34,10 +34,6 @@ */ /* - * To-Do: use memory pools for .buf recycling @?@ @?@ - */ - -/* * Rationale: * ---------- * @@ -87,15 +83,39 @@ * memBufInit(&buf, initial-size, absolute-maximum); * * -- "pack" (no need to handle offsets or check for overflows) - * memBufPrintf(&buf, ...); + * memBufPrintf(&buf, "format", ...); * ... * * -- write - * comm_write_mbuf(fd, buf, handler, data); + * comm_write_mbuf(fd, &buf, handler, data); * * -- *iff* you did not give the buffer away, free it yourself * -- memBufClean(&buf); * } + * + * or alternatively using pointers and references + * + * { + * -- setup + * MemBuf *bufp = memBufCreate(initial-size, absolute-maximum); + * MemBuf *otherp; + * + * -- "pack" (no need to handle offsets or check for overflows) + * memBufPrintf(bufp, "format", ...); + * ... + * + * -- write + * comm_write_mbuf(fd, bufp, handler, data); + * + * -- reference + * otherp = cbdataReference(bufp); + * + * -- destroy reference + * cbdataUnreference(&otherp) + * + * -- free + * memBufFree(&bufp) + * } */ @@ -107,10 +127,56 @@ #define MEM_BUF_INIT_SIZE (2*1024) #define MEM_BUF_MAX_SIZE (2*1000*1024*1024) - /* local routines */ static void memBufGrow(MemBuf * mb, mb_size_t min_cap); +/* Define data types */ +#define MEM_BUF_MIN_SIZE 64 +typedef struct {char *buf; char _buf[64];} MemBuf64; CBDATA_TYPE(MemBuf64); +typedef struct {char *buf; char _buf[128];} MemBuf128; CBDATA_TYPE(MemBuf128); +typedef struct {char *buf; char _buf[256];} MemBuf256; CBDATA_TYPE(MemBuf256); +typedef struct {char *buf; char _buf[512];} MemBuf512; CBDATA_TYPE(MemBuf512); +typedef struct {char *buf; char _buf[1024];} MemBuf1K; CBDATA_TYPE(MemBuf1K); +typedef struct {char *buf; char _buf[2048];} MemBuf2K; CBDATA_TYPE(MemBuf2K); +typedef struct {char *buf; char _buf[4096];} MemBuf4K; CBDATA_TYPE(MemBuf4K); +typedef struct {char *buf; char _buf[8192];} MemBuf8K; CBDATA_TYPE(MemBuf8K); +typedef struct {char *buf; char _buf[16384];} MemBuf16K; CBDATA_TYPE(MemBuf16K); +typedef struct {char *buf; char _buf[32768];} MemBuf32K; CBDATA_TYPE(MemBuf32K); +typedef struct {char *buf; char _buf[65535];} MemBuf64K; CBDATA_TYPE(MemBuf64K); +typedef struct {char *buf; int size;} MemBufLarge; CBDATA_TYPE(MemBufLarge); + +static FREE memBufFreeLarge; + +/* initialize the membuf module */ +void +memBuf_module_init(void) +{ + CBDATA_INIT_TYPE(MemBuf64); + CBDATA_INIT_TYPE(MemBuf128); + CBDATA_INIT_TYPE(MemBuf256); + CBDATA_INIT_TYPE(MemBuf512); + CBDATA_INIT_TYPE(MemBuf1K); + CBDATA_INIT_TYPE(MemBuf2K); + CBDATA_INIT_TYPE(MemBuf4K); + CBDATA_INIT_TYPE(MemBuf8K); + CBDATA_INIT_TYPE(MemBuf16K); + CBDATA_INIT_TYPE(MemBuf32K); + CBDATA_INIT_TYPE(MemBuf64K); + CBDATA_INIT_TYPE_FREECB(MemBufLarge, memBufFreeLarge); +} + +void +memBuf_module_shutdown(void) +{ +} + +/* free functions */ +void +memBufFreeLarge(void *data) +{ + char **p = data; + safe_free(*p); +} /* init with defaults */ void @@ -127,11 +193,10 @@ assert(mb); assert(szInit > 0 && szMax > 0); - mb->buf = NULL; mb->size = 0; mb->max_capacity = szMax; mb->capacity = 0; - mb->freefunc = NULL; + mb->bufp = NULL; memBufGrow(mb, szInit); } @@ -144,12 +209,8 @@ memBufClean(MemBuf * mb) { assert(mb); - assert(mb->buf); - assert(mb->freefunc); /* not frozen */ - (*mb->freefunc) (mb->buf); /* free */ - mb->freefunc = NULL; /* freeze */ - mb->buf = NULL; + cbdataFree(mb->bufp); mb->size = mb->capacity = 0; } @@ -163,10 +224,16 @@ if (memBufIsNull(mb)) { memBufDefInit(mb); } else { - assert(mb->freefunc); /* not frozen */ /* reset */ - memset(mb->buf, 0, mb->capacity); mb->size = 0; + if (cbdataLocked(mb->bufp)) { + /* oops.. the buffer is in use somewhere.. create a new one */ + cbdataFree(mb->bufp); + memBufGrow(mb, mb->capacity); + } else { + /* reuse the existing buffer */ + memset(*mb->bufp, 0, mb->capacity); + } } } @@ -175,9 +242,9 @@ memBufIsNull(MemBuf * mb) { assert(mb); - if (!mb->buf && !mb->max_capacity && !mb->capacity && !mb->size) + if (!mb->bufp && !mb->max_capacity && !mb->capacity && !mb->size) return 1; /* is null (not initialized) */ - assert(mb->buf && mb->max_capacity && mb->capacity); /* paranoid */ + assert(mb->bufp && mb->max_capacity && mb->capacity); /* paranoid */ return 0; } @@ -187,14 +254,12 @@ memBufAppend(MemBuf * mb, const char *buf, mb_size_t sz) { assert(mb && buf && sz >= 0); - assert(mb->buf); - assert(mb->freefunc); /* not frozen */ if (sz > 0) { if (mb->size + sz > mb->capacity) memBufGrow(mb, mb->size + sz); assert(mb->size + sz <= mb->capacity); /* paranoid */ - xmemcpy(mb->buf + mb->size, buf, sz); + xmemcpy(*mb->bufp + mb->size, buf, sz); mb->size += sz; } } @@ -230,138 +295,115 @@ { int sz = 0; assert(mb && fmt); - assert(mb->buf); - assert(mb->freefunc); /* not frozen */ + assert(mb->bufp); /* assert in Grow should quit first, but we do not want to have a scary infinite loop */ while (mb->capacity <= mb->max_capacity) { mb_size_t free_space = mb->capacity - mb->size; /* put as much as we can */ - sz = vsnprintf(mb->buf + mb->size, free_space, fmt, vargs); + sz = vsnprintf(*mb->bufp + mb->size, free_space, fmt, vargs); /* check for possible overflow */ - /* snprintf on Linuz returns -1 on overflows */ - /* snprintf on FreeBSD returns at least free_space on overflows */ - if (sz < 0 || sz >= free_space) + if (sz >= free_space) { + /* snprintf on FreeBSD returns at least free_space on overflows */ + memBufGrow(mb, mb->size + free_space + 1); + } else if (sz < 0) { + /* snprintf on old (libc5) Linux returns -1 on overflows */ memBufGrow(mb, mb->capacity + 1); - else + } else break; } mb->size += sz; /* on Linux and FreeBSD, '\0' is not counted in return value */ /* on XXX it might be counted */ /* check that '\0' is appended and not counted */ - if (!mb->size || mb->buf[mb->size - 1]) { - assert(!mb->buf[mb->size]); + if (!mb->size || (*mb->bufp)[mb->size - 1]) { + assert(!(*mb->bufp)[mb->size]); } else { mb->size--; } } -/* - * returns free() function to be used. - * Important: - * calling this function "freezes" mb, - * do not _update_ mb after that in any way - * (you still can read-access .buf and .size) - */ -FREE * -memBufFreeFunc(MemBuf * mb) -{ - FREE *ff; - assert(mb); - assert(mb->buf); - assert(mb->freefunc); /* not frozen */ - - ff = mb->freefunc; - mb->freefunc = NULL; /* freeze */ - return ff; -} - /* grows (doubles) internal buffer to satisfy required minimal capacity */ static void memBufGrow(MemBuf * mb, mb_size_t min_cap) { mb_size_t new_cap; - MemBuf old_mb; + char **old_bufp; + mb_size_t old_size; assert(mb); assert(mb->capacity < min_cap); + assert(min_cap <= mb->max_capacity); /* no overflow */ + /* determine next capacity */ new_cap = mb->capacity; - if (new_cap > 0) - while (new_cap < min_cap) - new_cap *= 2; /* double */ - else - new_cap = min_cap; - - /* last chance to fit before we assert(!overflow) */ - if (new_cap > mb->max_capacity) - new_cap = mb->max_capacity; - - assert(new_cap <= mb->max_capacity); /* no overflow */ - assert(new_cap > mb->capacity); /* progress */ - - old_mb = *mb; + if (new_cap == 0) + new_cap = MEM_BUF_MIN_SIZE; /* start doubling at a nice round value */ + while (new_cap < min_cap) + new_cap *= 2; /* double */ + + old_size = mb->size; + old_bufp = cbdataReference(mb->bufp); + cbdataFree(mb->bufp); /* allocate new memory */ switch (new_cap) { +#define NEW_MEMBUFP(type) \ + { \ + type *new_bufp = cbdataAlloc(type); \ + new_bufp->buf = new_bufp->_buf; \ + mb->bufp = (char **)new_bufp; \ + } + case 64: + NEW_MEMBUFP(MemBuf64); + break; + case 128: + NEW_MEMBUFP(MemBuf128); + break; + case 256: + NEW_MEMBUFP(MemBuf256); + break; + case 512: + NEW_MEMBUFP(MemBuf512); + break; + case 1024: + NEW_MEMBUFP(MemBuf1K); + break; case 2048: - mb->buf = memAllocate(MEM_2K_BUF); - mb->freefunc = &memFree2K; + NEW_MEMBUFP(MemBuf2K); break; case 4096: - mb->buf = memAllocate(MEM_4K_BUF); - mb->freefunc = &memFree4K; + NEW_MEMBUFP(MemBuf4K); break; case 8192: - mb->buf = memAllocate(MEM_8K_BUF); - mb->freefunc = &memFree8K; + NEW_MEMBUFP(MemBuf8K); break; case 16384: - mb->buf = memAllocate(MEM_16K_BUF); - mb->freefunc = &memFree16K; + NEW_MEMBUFP(MemBuf16K); break; case 32768: - mb->buf = memAllocate(MEM_32K_BUF); - mb->freefunc = &memFree32K; + NEW_MEMBUFP(MemBuf32K); break; case 65536: - mb->buf = memAllocate(MEM_64K_BUF); - mb->freefunc = &memFree64K; + NEW_MEMBUFP(MemBuf64K); break; default: - /* recycle if old buffer was not "pool"ed */ - if (old_mb.freefunc == &xfree) { - mb->buf = xrealloc(old_mb.buf, new_cap); - old_mb.buf = NULL; - old_mb.freefunc = NULL; - /* init tail, just in case */ - memset(mb->buf + mb->size, 0, new_cap - mb->size); - } else { - mb->buf = xcalloc(1, new_cap); - mb->freefunc = &xfree; + { + MemBufLarge *new_bufp = cbdataAlloc(MemBufLarge); + new_bufp->buf = xmalloc(new_cap); + mb->bufp = (char **)new_bufp; \ } } - /* copy and free old buffer if needed */ - if (old_mb.buf && old_mb.freefunc) { - xmemcpy(mb->buf, old_mb.buf, old_mb.size); - (*old_mb.freefunc) (old_mb.buf); - } else { - assert(!old_mb.buf && !old_mb.freefunc); + if (old_bufp) { + /* copy old buffer */ + xmemcpy(*mb->bufp, *old_bufp, mb->size); + cbdataUnreference(old_bufp); } + /* init tail, just in case */ + memset(*mb->bufp + mb->size, 0, new_cap - mb->size); + /* done */ mb->capacity = new_cap; } - - -/* Reports */ - -/* puts report on MemBuf _module_ usage into mb */ -void -memBufReport(MemBuf * mb) -{ - assert(mb); - memBufPrintf(mb, "memBufReport is not yet implemented @?@\n"); -} Index: squid/src/MemPool.c diff -u squid/src/MemPool.c:1.6 squid/src/MemPool.c:1.5.12.3 --- squid/src/MemPool.c:1.6 Wed Oct 24 02:42:11 2001 +++ squid/src/MemPool.c Sat Nov 17 05:11:57 2001 @@ -159,10 +159,10 @@ static void memPoolMeterReport(const MemPoolMeter * pm, size_t obj_size, - int alloc_count, int inuse_count, int idle_count, StoreEntry * e) + int alloc_count, int inuse_count, int idle_count, MemBuf *out) { assert(pm); - storeAppendPrintf(e, "%d\t %ld\t %ld\t %.2f\t %d\t %d\t %ld\t %ld\t %d\t %d\t %ld\t %ld\t %ld\t %.2f\t %.2f\t %.2f\t %ld\n", + memBufPrintf(out, "%d\t %ld\t %ld\t %.2f\t %d\t %d\t %ld\t %ld\t %d\t %d\t %ld\t %ld\t %ld\t %.2f\t %.2f\t %.2f\t %ld\n", /* alloc */ alloc_count, (long int) toKB(obj_size * pm->alloc.level), @@ -323,29 +323,31 @@ return TheMeter.alloc.level; } -void -memPoolReport(const MemPool * pool, StoreEntry * e) +static void +memPoolReport(const MemPool * pool, MemBuf *out) { assert(pool); - storeAppendPrintf(e, "%-20s\t %4d\t ", + memBufPrintf(out, "%-20s\t %4d\t ", pool->label, (int) pool->obj_size); memPoolMeterReport(&pool->meter, pool->obj_size, pool->meter.alloc.level, pool->meter.inuse.level, pool->meter.idle.level, - e); + out); } -void -memReport(StoreEntry * e) +IOBuf * +memReport(void) { + IOBuf *out; size_t overhd_size = 0; int alloc_count = 0; int inuse_count = 0; int idle_count = 0; int i; + out = IOBufAlloc(8192); /* caption */ - storeAppendPrintf(e, "Current memory usage:\n"); + memBufPrintf(out, "Current memory usage:\n"); /* heading */ - storeAppendPrintf(e, "Pool\t Obj Size\t" + memBufPrintf(out, "Pool\t Obj Size\t" "Allocated\t\t\t\t\t In Use\t\t\t\t Idle\t\t\t Allocations Saved\t\t\t Hit Rate\t\n" " \t (bytes)\t" "(#)\t (KB)\t high (KB)\t high (hrs)\t impact (%%total)\t" @@ -359,7 +361,7 @@ for (i = 0; i < Pools.count; i++) { const MemPool *pool = Pools.items[i]; if (memPoolWasUsed(pool)) { - memPoolReport(pool, e); + memPoolReport(pool, out); alloc_count += pool->meter.alloc.level; inuse_count += pool->meter.inuse.level; idle_count += pool->meter.idle.level; @@ -370,14 +372,53 @@ } overhd_size += sizeof(Pools) + Pools.capacity * sizeof(MemPool *); /* totals */ - storeAppendPrintf(e, "%-20s\t %-4s\t ", "Total", "-"); - memPoolMeterReport(&TheMeter, 1, alloc_count, inuse_count, idle_count, e); - storeAppendPrintf(e, "Cumulative allocated volume: %s\n", gb_to_str(&mem_traffic_volume)); + memBufPrintf(out, "%-20s\t %-4s\t ", "Total", "-"); + memPoolMeterReport(&TheMeter, 1, alloc_count, inuse_count, idle_count, out); + memBufPrintf(out, "Cumulative allocated volume: %s\n", gb_to_str(&mem_traffic_volume)); /* overhead */ - storeAppendPrintf(e, "Current overhead: %ld bytes (%.3f%%)\n", + memBufPrintf(out, "Current overhead: %ld bytes (%.3f%%)\n", (long int) overhd_size, xpercent(overhd_size, TheMeter.inuse.level)); /* limits */ - storeAppendPrintf(e, "Idle pool limit: %.2f MB\n", toMB(mem_idle_limit)); - storeAppendPrintf(e, "memPoolAlloc calls: %d\n", mem_pool_alloc_calls); - storeAppendPrintf(e, "memPoolFree calls: %d\n", mem_pool_free_calls); + memBufPrintf(out, "Idle pool limit: %.2f MB\n", toMB(mem_idle_limit)); + memBufPrintf(out, "memPoolAlloc calls: %d\n", mem_pool_alloc_calls); + memBufPrintf(out, "memPoolFree calls: %d\n", mem_pool_free_calls); + return out; } + +void +gb_flush(gb_t * g) +{ + g->gb += (g->bytes >> 30); + g->bytes &= (1 << 30) - 1; +} + +double +gb_to_double(const gb_t * g) +{ + return ((double) g->gb) * ((double) (1 << 30)) + ((double) g->bytes); +} + +const char * +gb_to_str(const gb_t * g) +{ + /* + * it is often convenient to call gb_to_str several times for _one_ printf + */ +#define max_cc_calls 5 + typedef char GbBuf[32]; + static GbBuf bufs[max_cc_calls]; + static int call_id = 0; + double value = gb_to_double(g); + char *buf = bufs[call_id++]; + if (call_id >= max_cc_calls) + call_id = 0; + /* select format */ + if (value < 1e9) + snprintf(buf, sizeof(GbBuf), "%.2f MB", value / 1e6); + else if (value < 1e12) + snprintf(buf, sizeof(GbBuf), "%.2f GB", value / 1e9); + else + snprintf(buf, sizeof(GbBuf), "%.2f TB", value / 1e12); + return buf; +} + Index: squid/src/acl.c diff -u squid/src/acl.c:1.42 squid/src/acl.c:1.21.8.7 --- squid/src/acl.c:1.42 Tue Nov 13 14:19:33 2001 +++ squid/src/acl.c Sat Nov 17 05:11:57 2001 @@ -2287,7 +2287,7 @@ memBufPrintf(&mb, "-%s", inet_ntoa(ip->addr2)); if (ip->mask.s_addr != no_addr.s_addr) memBufPrintf(&mb, "/%s", inet_ntoa(ip->mask)); - wordlistAdd(W, mb.buf); + wordlistAdd(W, *mb.bufp); memBufClean(&mb); } Index: squid/src/asn.c diff -u squid/src/asn.c:1.15 squid/src/asn.c:1.9.8.3 --- squid/src/asn.c:1.15 Tue Nov 13 14:19:33 2001 +++ squid/src/asn.c Sat Nov 17 05:11:57 2001 @@ -199,7 +199,7 @@ if ((e = storeGetPublic(asres, METHOD_GET)) == NULL) { e = storeCreateEntry(asres, asres, null_request_flags, METHOD_GET); asState->sc = storeClientListAdd(e, asState); - fwdStart(-1, e, asState->request); + fwdStart(NULL, e, asState->request); } else { storeLockObject(e); asState->sc = storeClientListAdd(e, asState); Index: squid/src/authenticate.c diff -u squid/src/authenticate.c:1.22 squid/src/authenticate.c:1.12.8.4 --- squid/src/authenticate.c:1.22 Sat Oct 27 03:15:54 2001 +++ squid/src/authenticate.c Sat Nov 17 05:11:57 2001 @@ -487,8 +487,8 @@ * not had bungled connection oriented authentication happen on it. */ debug(28, 9) ("authenticateAuthenticate: header %s.\n", proxy_auth); if (*auth_user_request == NULL) { - debug(28, 9) ("authenticateAuthenticate: This is a new checklist test on FD:%d\n", - conn->fd); + debug(28, 9) ("authenticateAuthenticate: This is a new checklist test on FH:%p\n", + conn->fh); if ((!request->auth_user_request) && (conn->auth_type == AUTH_UNKNOWN)) { /* beginning of a new request check */ Index: squid/src/cache_cf.c diff -u squid/src/cache_cf.c:1.38 squid/src/cache_cf.c:1.18.8.8 --- squid/src/cache_cf.c:1.38 Wed Oct 24 02:42:12 2001 +++ squid/src/cache_cf.c Sat Nov 17 05:11:57 2001 @@ -114,70 +114,6 @@ } void -wordlistDestroy(wordlist ** list) -{ - wordlist *w = NULL; - while ((w = *list) != NULL) { - *list = w->next; - safe_free(w->key); - memFree(w, MEM_WORDLIST); - } - *list = NULL; -} - -const char * -wordlistAdd(wordlist ** list, const char *key) -{ - while (*list) - list = &(*list)->next; - *list = memAllocate(MEM_WORDLIST); - (*list)->key = xstrdup(key); - (*list)->next = NULL; - return (*list)->key; -} - -void -wordlistJoin(wordlist ** list, wordlist ** wl) -{ - while (*list) - list = &(*list)->next; - *list = *wl; - *wl = NULL; -} - -void -wordlistAddWl(wordlist ** list, wordlist * wl) -{ - while (*list) - list = &(*list)->next; - for (; wl; wl = wl->next, list = &(*list)->next) { - *list = memAllocate(MEM_WORDLIST); - (*list)->key = xstrdup(wl->key); - (*list)->next = NULL; - } -} - -void -wordlistCat(const wordlist * w, MemBuf * mb) -{ - while (NULL != w) { - memBufPrintf(mb, "%s\n", w->key); - w = w->next; - } -} - -wordlist * -wordlistDup(const wordlist * w) -{ - wordlist *D = NULL; - while (NULL != w) { - wordlistAdd(&D, w->key); - w = w->next; - } - return D; -} - -void intlistDestroy(intlist ** list) { intlist *w = NULL; @@ -285,9 +221,6 @@ memset(&Config2, '\0', sizeof(SquidConfig2)); /* init memory as early as possible */ memConfigure(); - /* Sanity checks */ - if (Config.cacheSwap.swapDirs == NULL) - fatal("No cache_dir's specified in config file"); /* calculate Config.Swap.maxSize */ storeDirConfigure(); if (0 == Config.Swap.maxSize) @@ -2227,6 +2160,7 @@ self_destruct(); } s = xcalloc(1, sizeof(*s)); + s->s.sin_family = AF_INET; s->s.sin_port = htons(port); if (NULL == host) s->s.sin_addr = any_addr; Index: squid/src/cache_manager.c diff -u squid/src/cache_manager.c:1.7 squid/src/cache_manager.c:1.6.12.2 --- squid/src/cache_manager.c:1.7 Fri Feb 23 13:03:30 2001 +++ squid/src/cache_manager.c Wed Sep 12 14:16:47 2001 @@ -192,7 +192,7 @@ } void -cachemgrStart(int fd, request_t * request, StoreEntry * entry) +cachemgrStart(request_t * request, StoreEntry * entry) { cachemgrStateData *mgr = NULL; ErrorState *err = NULL; @@ -209,7 +209,7 @@ storeLockObject(entry); entry->expires = squid_curtime; debug(16, 5) ("CACHEMGR: %s requesting '%s'\n", - fd_table[fd].ipaddr, mgr->action); + inet_ntoa(request->client_addr), mgr->action); /* get additional info from request headers */ cachemgrParseHeaders(mgr, request); /* Check password */ @@ -222,11 +222,11 @@ if (mgr->passwd) debug(16, 1) ("CACHEMGR: %s@%s: incorrect password for '%s'\n", mgr->user_name ? mgr->user_name : "", - fd_table[fd].ipaddr, mgr->action); + inet_ntoa(request->client_addr), mgr->action); else debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n", mgr->user_name ? mgr->user_name : "", - fd_table[fd].ipaddr, mgr->action); + inet_ntoa(request->client_addr), mgr->action); err->request = requestLink(request); rep = errorBuildReply(err); errorStateFree(err); @@ -246,7 +246,7 @@ } debug(16, 1) ("CACHEMGR: %s@%s requesting '%s'\n", mgr->user_name ? mgr->user_name : "", - fd_table[fd].ipaddr, mgr->action); + inet_ntoa(request->client_addr), mgr->action); /* retrieve object requested */ a = cachemgrFindAction(mgr->action); assert(a != NULL); Index: squid/src/cbdata.c diff -u squid/src/cbdata.c:1.14 squid/src/cbdata.c:1.9.8.6 --- squid/src/cbdata.c:1.14 Thu Oct 18 13:52:11 2001 +++ squid/src/cbdata.c Sat Nov 17 05:11:58 2001 @@ -84,12 +84,10 @@ } data; } cbdata; -static OBJH cbdataDump; - struct { MemPool *pool; FREE *free_func; -} *cbdata_index = NULL; +} *cbdata_index = NULL; int cbdata_types = 0; #define OFFSET_OF(type, member) ((int)(char *)&((type *)0L)->member) @@ -127,9 +125,6 @@ cbdataInit(void) { debug(45, 3) ("cbdataInit\n"); - cachemgrRegister("cbdata", - "Callback Data Registry Contents", - cbdataDump, 0, 1); #define CREATE_CBDATA(type) cbdataInitType(CBDATA_##type, #type, sizeof(type), NULL) #define CREATE_CBDATA_FREE(type, free_func) cbdataInitType(CBDATA_##type, #type, sizeof(type), free_func) CREATE_CBDATA(acl_access); @@ -274,10 +269,3 @@ assert(c->locks > 0); return c->valid; } - -static void -cbdataDump(StoreEntry * sentry) -{ - storeAppendPrintf(sentry, "%d cbdata entries\n", cbdataCount); - storeAppendPrintf(sentry, "see also memory pools section\n"); -} Index: squid/src/client_side.c diff -u squid/src/client_side.c:1.45 squid/src/client_side.c:1.19.2.12 --- squid/src/client_side.c:1.45 Sun Nov 18 10:57:17 2001 +++ squid/src/client_side.c Wed Nov 21 18:19:01 2001 @@ -35,38 +35,6 @@ #include "squid.h" -#if IPF_TRANSPARENT -#if HAVE_SYS_IOCTL_H -#include -#endif -#include -#include -#if HAVE_IP_FIL_COMPAT_H -#include -#elif HAVE_NETINET_IP_FIL_COMPAT_H -#include -#elif HAVE_IP_COMPAT_H -#include -#elif HAVE_NETINET_IP_COMPAT_H -#include -#endif -#if HAVE_IP_FIL_H -#include -#elif HAVE_NETINET_IP_FIL_H -#include -#endif -#if HAVE_IP_NAT_H -#include -#elif HAVE_NETINET_IP_NAT_H -#include -#endif -#endif - -#if LINUX_NETFILTER -#include -#endif - - #if LINGERING_CLOSE #define comm_close comm_lingering_close #endif @@ -77,19 +45,22 @@ /* Local functions */ -static CWCB clientWriteComplete; -static CWCB clientWriteBodyComplete; -static PF clientReadRequest; +static COMMIOCB clientWriteComplete; +static COMMIOCB clientWriteBodyComplete; +static COMMIOCB clientReadRequest; +static void clientReadRequest2(ConnStateData * conn); +#if NOT_YET_PORTED static PF connStateFree; static PF requestTimeout; static PF clientLifetimeTimeout; +#endif static int clientCheckTransferDone(clientHttpRequest *); static int clientGotNotEnough(clientHttpRequest *); static void checkFailureRatio(err_type, hier_code); static void clientProcessMiss(clientHttpRequest *); static void clientBuildReplyHeader(clientHttpRequest * http, HttpReply * rep); static clientHttpRequest *parseHttpRequestAbort(ConnStateData * conn, const char *uri); -static clientHttpRequest *parseHttpRequest(ConnStateData *, method_t *, int *, char **, size_t *); +static clientHttpRequest *parseHttpRequest(ConnStateData *, char **, size_t *, method_t *, int *, char **, size_t *); static RH clientRedirectDone; static void clientCheckNoCache(clientHttpRequest *); static void clientCheckNoCacheDone(int answer, void *data); @@ -112,7 +83,9 @@ static int clientCachable(clientHttpRequest * http); static int clientHierarchical(clientHttpRequest * http); static int clientCheckContentLength(request_t * r); +#if NOT_YET_PORTED static DEFER httpAcceptDefer; +#endif static log_type clientProcessRequest2(clientHttpRequest * http); static int clientReplyBodyTooLarge(HttpReply *, ssize_t clen); static int clientRequestBodyTooLarge(int clen); @@ -329,7 +302,7 @@ #if HEADERS_LOG headersLog(0, 1, request->method, request); #endif - fd_note(http->conn->fd, http->uri); + ncomm_note(http->conn->fh, http->uri); clientCheckNoCache(http); } @@ -393,7 +366,7 @@ debug(33, 5) ("clientProcessExpired: lastmod %ld\n", (long int) entry->lastmod); http->entry = entry; http->out.offset = 0; - fwdStart(http->conn->fd, http->entry, http->request); + fwdStart(http->conn->fh, http->entry, http->request); /* Register with storage manager to receive updates when data comes in. */ if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) debug(33, 0) ("clientProcessExpired: found ENTRY_ABORTED object\n"); @@ -793,7 +766,7 @@ httpHeaderPackInto(&request->header, &p); http->al.http.method = request->method; http->al.http.version = request->http_ver; - http->al.headers.request = xstrdup(mb.buf); + http->al.headers.request = xstrdup(*mb.bufp); http->al.hier = request->hier; if (request->auth_user_request) { http->al.cache.authuser = xstrdup(authenticateUserRequestUsername(request->auth_user_request)); @@ -850,13 +823,14 @@ cbdataFree(http); } +#if NOT_YET_PORTED /* This is a handler normally called by comm_close() */ static void -connStateFree(int fd, void *data) +connStateFree(filehandle *fh, void *data) { ConnStateData *connState = data; clientHttpRequest *http; - debug(33, 3) ("connStateFree: FD %d\n", fd); + debug(33, 3) ("connStateFree: FH %p\n", fh); assert(connState != NULL); clientdbEstablished(connState->peer.sin_addr, -1); /* decrement */ while ((http = connState->chr) != NULL) { @@ -868,21 +842,11 @@ authenticateAuthUserRequestUnlock(connState->auth_user_request); connState->auth_user_request = NULL; authenticateOnCloseConnection(connState); - if (connState->in.size == CLIENT_REQ_BUF_SZ) - memFree(connState->in.buf, MEM_CLIENT_REQ_BUF); - else - safe_free(connState->in.buf); - /* XXX account connState->in.buf */ + cbdataUnreference(connState->in); pconnHistCount(0, connState->nrequests); cbdataFree(connState); -#ifdef _SQUID_LINUX_ - /* prevent those nasty RST packets */ - { - char buf[SQUID_TCP_SO_RCVBUF]; - while (FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF) > 0); - } -#endif } +#endif static void clientInterpretRequestHeaders(clientHttpRequest * http) @@ -1584,8 +1548,8 @@ */ e->timestamp = timestamp; http->entry = e; - httpReplyParse(e->mem_obj->reply, mb.buf, mb.size); - storeAppend(e, mb.buf, mb.size); + httpReplyParse(e->mem_obj->reply, *mb.bufp, mb.size); + storeAppend(e, *mb.bufp, mb.size); memBufClean(&mb); storeComplete(e); } @@ -1826,7 +1790,6 @@ clientHttpRequest *http = data; StoreEntry *entry = http->entry; ConnStateData *conn = http->conn; - int fd = conn->fd; HttpReply *rep = NULL; const char *body_buf = buf; ssize_t body_size = size; @@ -1837,8 +1800,8 @@ assert(http->request != NULL); dlinkDelete(&http->active, &ClientActiveRequests); dlinkAdd(http, &http->active, &ClientActiveRequests); - debug(33, 5) ("clientSendMoreData: FD %d '%s', out.offset=%ld \n", - fd, storeUrl(entry), (long int) http->out.offset); + debug(33, 5) ("clientSendMoreData: FH %p '%s', out.offset=%ld \n", + conn->fh, storeUrl(entry), (long int) http->out.offset); if (conn->chr != http) { /* there is another object in progress, defer this one */ debug(33, 1) ("clientSendMoreData: Deferring %s\n", storeUrl(entry)); @@ -1846,17 +1809,17 @@ return; } else if (entry && EBIT_TEST(entry->flags, ENTRY_ABORTED)) { /* call clientWriteComplete so the client socket gets closed */ - clientWriteComplete(fd, NULL, 0, COMM_OK, http); + clientWriteComplete(conn->fh, NULL, 0, 0, 0, http); memFree(buf, MEM_CLIENT_SOCK_BUF); return; } else if (size < 0) { /* call clientWriteComplete so the client socket gets closed */ - clientWriteComplete(fd, NULL, 0, COMM_OK, http); + clientWriteComplete(conn->fh, NULL, 0, 0, 0, http); memFree(buf, MEM_CLIENT_SOCK_BUF); return; } else if (size == 0) { /* call clientWriteComplete so the client socket gets closed */ - clientWriteComplete(fd, NULL, 0, COMM_OK, http); + clientWriteComplete(conn->fh, NULL, 0, 0, 0, http); memFree(buf, MEM_CLIENT_SOCK_BUF); return; } @@ -1931,11 +1894,11 @@ /* reset range iterator */ http->range_iter.pos = HttpHdrRangeInitPos; } else if (!http->request->range) { - /* Avoid copying to MemBuf for non-range requests */ /* Note, if we're here, then 'rep' is known to be NULL */ + IOBuf *iob = IOBufCreate(buf, size); /* should get an IOBuf from start... */ http->out.offset += body_size; - comm_write(fd, buf, size, clientWriteBodyComplete, http, NULL); - /* NULL because clientWriteBodyComplete frees it */ + ncomm_write(conn->fh, iob, clientWriteBodyComplete, http); + cbdataUnreference(iob); return; } if (http->request->method == METHOD_HEAD) { @@ -1986,7 +1949,7 @@ if (!http->request->range && http->request->method == METHOD_GET) assert(check_size == size); /* write */ - comm_write_mbuf(fd, mb, clientWriteComplete, http); + ncomm_write_mbuf(conn->fh, mb, clientWriteComplete, http); /* if we don't do it, who will? */ memFree(buf, MEM_CLIENT_SOCK_BUF); } @@ -1998,14 +1961,13 @@ * the headers probably go through here. */ static void -clientWriteBodyComplete(int fd, char *buf, size_t size, int errflag, void *data) +clientWriteBodyComplete(filehandle *fh, IOBuf *buf, int offset, int size, int error, void *cbdata) { /* * NOTE: clientWriteComplete doesn't currently use its "buf" * (second) argument, so we pass in NULL. */ - clientWriteComplete(fd, NULL, size, errflag, data); - memFree(buf, MEM_CLIENT_SOCK_BUF); + clientWriteComplete(fh, NULL, offset, size, error, cbdata); } static void @@ -2013,28 +1975,19 @@ { ConnStateData *conn = http->conn; StoreEntry *entry; - debug(33, 3) ("clientKeepaliveNextRequest: FD %d\n", conn->fd); - conn->defer.until = 0; /* Kick it to read a new request */ + debug(33, 3) ("clientKeepaliveNextRequest: FH %p\n", conn->fh); httpRequestFree(http); if ((http = conn->chr) == NULL) { - debug(33, 5) ("clientKeepaliveNextRequest: FD %d reading next req\n", - conn->fd); - fd_note(conn->fd, "Waiting for next request"); + debug(33, 5) ("clientKeepaliveNextRequest: FH %p reading next req\n", + conn->fh); + ncomm_note(conn->fh, "Waiting for next request"); /* * Set the timeout BEFORE calling clientReadRequest(). */ - commSetTimeout(conn->fd, Config.Timeout.pconn, requestTimeout, conn); - /* - * CYGWIN has a problem and is blocking on read() requests when there - * is no data present. - * This hack may hit performance a little, but it's better than - * blocking!. - */ -#ifdef _SQUID_CYGWIN_ - commSetSelect(conn->fd, COMM_SELECT_READ, clientReadRequest, conn, 0); -#else - clientReadRequest(conn->fd, conn); /* Read next request */ +#if NOT_YET_PORTED + commSetTimeout(conn->fh, Config.Timeout.pconn, requestTimeout, conn); #endif + clientReadRequest2(conn); /* Read next request */ /* * Note, the FD may be closed at this point. */ @@ -2044,8 +1997,8 @@ * execution will resume after the operation completes. */ } else { - debug(33, 1) ("clientKeepaliveNextRequest: FD %d Sending next\n", - conn->fd); + debug(33, 1) ("clientKeepaliveNextRequest: FH %p Sending next\n", + conn->fh); assert(entry); if (0 == storeClientCopyPending(http->sc, entry, http)) { if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) @@ -2062,14 +2015,14 @@ } static void -clientWriteComplete(int fd, char *bufnotused, size_t size, int errflag, void *data) +clientWriteComplete(filehandle *fh, IOBuf *buf, int offset, int size, int errflag, void *data) { clientHttpRequest *http = data; StoreEntry *entry = http->entry; int done; http->out.size += size; - debug(33, 5) ("clientWriteComplete: FD %d, sz %ld, err %d, off %ld, len %d\n", - fd, (long int) size, errflag, (long int) http->out.offset, entry ? objectLen(entry) : 0); + debug(33, 5) ("clientWriteComplete: FH %p, sz %ld, err %d, off %ld, len %d\n", + fh, (long int)size, errflag, (long int) http->out.offset, entry ? objectLen(entry) : 0); if (size > 0) { kb_incr(&statCounter.client_http.kbytes_out, size); if (isTcpHit(http->log_type)) @@ -2079,31 +2032,31 @@ /* * just close the socket, httpRequestFree will abort if needed */ - comm_close(fd); + ncomm_close(fh); } else if (NULL == entry) { - comm_close(fd); /* yuk */ + ncomm_close(fh); /* yuk */ } else if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - comm_close(fd); + ncomm_close(fh); } else if ((done = clientCheckTransferDone(http)) != 0 || size == 0) { - debug(33, 5) ("clientWriteComplete: FD %d transfer is DONE\n", fd); + debug(33, 5) ("clientWriteComplete: FH %p transfer is DONE\n", fh); /* We're finished case */ if (httpReplyBodySize(http->request->method, entry->mem_obj->reply) < 0) { debug(33, 5) ("clientWriteComplete: closing, content_length < 0\n"); - comm_close(fd); + ncomm_close(fh); } else if (!done) { debug(33, 5) ("clientWriteComplete: closing, !done\n"); - comm_close(fd); + ncomm_close(fh); } else if (clientGotNotEnough(http)) { debug(33, 5) ("clientWriteComplete: client didn't get all it expected\n"); - comm_close(fd); + ncomm_close(fh); } else if (http->request->flags.proxy_keepalive) { - debug(33, 5) ("clientWriteComplete: FD %d Keeping Alive\n", fd); + debug(33, 5) ("clientWriteComplete: FH %p Keeping Alive\n", fh); clientKeepaliveNextRequest(http); } else { - comm_close(fd); + ncomm_close(fh); } } else if (clientReplyBodyTooLarge(entry->mem_obj->reply, http->out.offset)) { - comm_close(fd); + ncomm_close(fh); } else { /* More data will be coming from primary server; register with * storage manager. */ @@ -2269,7 +2222,7 @@ { char *url = http->uri; request_t *r = http->request; - int fd = http->conn->fd; + filehandle *fh = http->conn->fh; HttpReply *rep; http_version_t version; debug(33, 4) ("clientProcessRequest: %s '%s'\n", @@ -2277,7 +2230,7 @@ url); if (r->method == METHOD_CONNECT) { http->log_type = LOG_TCP_MISS; - sslStart(fd, url, r, &http->out.size, &http->al.http.code); + sslStart(fh, url, r, &http->out.size, &http->al.http.code); return; } else if (r->method == METHOD_PURGE) { clientPurgeRequest(http); @@ -2389,7 +2342,7 @@ } if (http->flags.internal) r->protocol = PROTO_INTERNAL; - fwdStart(http->conn->fd, http->entry, r); + fwdStart(http->conn->fh, http->entry, r); } static clientHttpRequest * @@ -2399,7 +2352,6 @@ http = cbdataAlloc(clientHttpRequest); http->conn = conn; http->start = current_time; - http->req_sz = conn->in.offset; http->uri = xstrdup(uri); http->log_uri = xstrndup(uri, MAX_URL); http->range_iter.boundary = StringNull; @@ -2415,10 +2367,10 @@ * a clientHttpRequest structure on success */ static clientHttpRequest * -parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, - char **prefix_p, size_t * req_line_sz_p) +parseHttpRequest(ConnStateData * conn, char ** buf_p, size_t *size_p, method_t * method_p, int *status, char **prefix_p, size_t * req_line_sz_p) { - char *inbuf = NULL; + char *inbuf; + char *buf = *buf_p; char *mstr = NULL; char *url = NULL; char *req_hdr = NULL; @@ -2432,32 +2384,28 @@ size_t req_sz; method_t method; clientHttpRequest *http = NULL; -#if IPF_TRANSPARENT - struct natlookup natLookup; - static int natfd = -1; - static int siocgnatl_cmd = SIOCGNATL & 0xff; - int x; -#endif -#if LINUX_NETFILTER - size_t sock_sz = sizeof(conn->me); -#endif - /* pre-set these values to make aborting simpler */ - *prefix_p = NULL; - *method_p = METHOD_NONE; - *status = -1; - - if ((req_sz = headersEnd(conn->in.buf, conn->in.offset)) == 0) { + if ((req_sz = headersEnd(*buf_p, *size_p)) == 0) { debug(33, 5) ("Incomplete request, waiting for end of headers\n"); *status = 0; return NULL; } - assert(req_sz <= conn->in.offset); - /* Use memcpy, not strdup! */ + assert(req_sz <= *size_p); + + /* Make a temporary (terminated) copy of the request line and headers */ inbuf = xmalloc(req_sz + 1); - xmemcpy(inbuf, conn->in.buf, req_sz); + xmemcpy(inbuf, *buf_p, req_sz); *(inbuf + req_sz) = '\0'; + /* Eat up the request line and headers from the input */ + *buf_p += req_sz; + *size_p -= req_sz; + + /* pre-set these values to make aborting simpler */ + *prefix_p = inbuf; + *method_p = METHOD_NONE; + *status = -1; + /* Barf on NULL characters in the headers */ if (strlen(inbuf) != req_sz) { debug(33, 1) ("parseHttpRequest: Requestheader contains NULL characters\n"); @@ -2537,7 +2485,7 @@ *req_line_sz_p = req_hdr - inbuf; debug(33, 3) ("parseHttpRequest: prefix_sz = %d, req_line_sz = %d\n", (int) prefix_sz, (int) *req_line_sz_p); - assert(prefix_sz <= conn->in.offset); + assert(prefix_sz == req_sz); /* Ok, all headers are received */ http = cbdataAlloc(clientHttpRequest); @@ -2547,7 +2495,7 @@ http->req_sz = prefix_sz; http->range_iter.boundary = StringNull; *prefix_p = xmalloc(prefix_sz + 1); - xmemcpy(*prefix_p, conn->in.buf, prefix_sz); + xmemcpy(*prefix_p, buf, prefix_sz); *(*prefix_p + prefix_sz) = '\0'; dlinkAdd(http, &http->active, &ClientActiveRequests); @@ -2611,75 +2559,6 @@ vport = (int) ntohs(http->conn->me.sin_port); else vport = (int) Config.Accel.port; -#if IPF_TRANSPARENT - natLookup.nl_inport = http->conn->me.sin_port; - natLookup.nl_outport = http->conn->peer.sin_port; - natLookup.nl_inip = http->conn->me.sin_addr; - natLookup.nl_outip = http->conn->peer.sin_addr; - natLookup.nl_flags = IPN_TCP; - if (natfd < 0) { - int save_errno; - enter_suid(); - natfd = open(IPL_NAT, O_RDONLY, 0); - save_errno = errno; - leave_suid(); - errno = save_errno; - } - if (natfd < 0) { - debug(50, 1) ("parseHttpRequest: NAT open failed: %s\n", - xstrerror()); - dlinkDelete(&http->active, &ClientActiveRequests); - xfree(http->uri); - cbdataFree(http); - xfree(inbuf); - return parseHttpRequestAbort(conn, "error:nat-open-failed"); - } - /* - * IP-Filter changed the type for SIOCGNATL between - * 3.3 and 3.4. It also changed the cmd value for - * SIOCGNATL, so at least we can detect it. We could - * put something in configure and use ifdefs here, but - * this seems simpler. - */ - if (63 == siocgnatl_cmd) { - struct natlookup *nlp = &natLookup; - x = ioctl(natfd, SIOCGNATL, &nlp); - } else { - x = ioctl(natfd, SIOCGNATL, &natLookup); - } - if (x < 0) { - if (errno != ESRCH) { - debug(50, 1) ("parseHttpRequest: NAT lookup failed: ioctl(SIOCGNATL)\n"); - close(natfd); - natfd = -1; - dlinkDelete(&http->active, &ClientActiveRequests); - xfree(http->uri); - cbdataFree(http); - xfree(inbuf); - return parseHttpRequestAbort(conn, "error:nat-lookup-failed"); - } else - snprintf(http->uri, url_sz, "http://%s:%d%s", - inet_ntoa(http->conn->me.sin_addr), - vport, url); - } else { - if (vport_mode) - vport = natLookup.nl_realport; - snprintf(http->uri, url_sz, "http://%s:%d%s", - inet_ntoa(natLookup.nl_realip), - vport, url); - } -#else -#if LINUX_NETFILTER - /* If the call fails the address structure will be unchanged */ - getsockopt(conn->fd, SOL_IP, SO_ORIGINAL_DST, &conn->me, &sock_sz); - debug(33, 5) ("parseHttpRequest: addr = %s", inet_ntoa(conn->me.sin_addr)); - if (vport_mode) - vport = (int) ntohs(http->conn->me.sin_port); -#endif - snprintf(http->uri, url_sz, "http://%s:%d%s", - inet_ntoa(http->conn->me.sin_addr), - vport, url); -#endif debug(33, 5) ("VHOST REWRITE: '%s'\n", http->uri); } else { url_sz = strlen(Config2.Accel.prefix) + strlen(url) + @@ -2705,6 +2584,7 @@ return http; } +#if OLD_COMM_CODE static int clientReadDefer(int fdnotused, void *data) { @@ -2714,8 +2594,220 @@ else return conn->defer.until > squid_curtime; } +#endif static void +clientReadRequest2(ConnStateData * conn) +{ + filehandle *fh = conn->fh; + request_t *request; + + /* Process request body if any */ + if (conn->body.callback != NULL) + clientProcessBody(conn); + + while (conn->in && conn->body.size_left == 0) { + clientHttpRequest **H, *http; + int nrequests; + method_t method; + char *prefix; + int parser_return_code; + char *buf = IOBufP(conn->in); + size_t size = IOBufSize(conn->in); + size_t req_line_sz; + /* Skip leading (and trailing) whitespace */ + while (size > 0 && xisspace(*buf)) { + buf++; + size--; + } + if (size == 0) + break; + /* Limit the number of concurrent requests to 2 */ + for (H = &conn->chr, nrequests = 0; *H; H = &(*H)->next, nrequests++); + if (nrequests >= (Config.onoff.pipeline_prefetch ? 2 : 1)) { + debug(33, 3) ("clientReadRequest: FH %p max concurrent requests reached\n", fh); + debug(33, 5) ("clientReadRequest: FH %p defering new request until one is done\n", fh); + return; + } + if (nrequests == 0) + ncomm_note(conn->fh, "Reading next request"); + /* Process request */ + http = parseHttpRequest(conn, + &buf, + &size, + &method, + &parser_return_code, + &prefix, + &req_line_sz); + if (!http) + safe_free(prefix); + if (http) { + IOBuf *newbuf = NULL; + assert(http->req_sz > 0); + assert(size >= 0); + /* + * If we read past the end of this request, move the remaining + * data to the beginning + */ + if (size > 0) + newbuf = IOBufCreate(buf, size); + cbdataUnreference(conn->in); + conn->in = cbdataReference(newbuf); + cbdataUnreference(newbuf); + + /* add to the client request queue */ + for (H = &conn->chr; *H; H = &(*H)->next); + *H = http; + conn->nrequests++; + /* + * I wanted to lock 'http' here since its callback data for + * clientLifetimeTimeout(), but there's no logical place to + * cbdataUnlock if the timeout never happens. Maybe its safe + * enough to assume that if the FD is open, and the timeout + * triggers, that 'http' is valid. + */ +#if NOT_YET_PORTED + commSetTimeout(fh, Config.Timeout.lifetime, clientLifetimeTimeout, http); +#endif + if (parser_return_code < 0) { + ErrorState *err; + debug(33, 1) ("clientReadRequest: FH %p Invalid Request\n", fh); + err = errorCon(ERR_INVALID_REQ, HTTP_BAD_REQUEST); + err->request_hdrs = xstrdup(buf); /* XXX NULL termination! */ + http->entry = clientCreateStoreEntry(http, method, null_request_flags); + errorAppendEntry(http->entry, err); + safe_free(prefix); + break; + } + if ((request = urlParse(method, http->uri)) == NULL) { + ErrorState *err; + debug(33, 5) ("Invalid URL: %s\n", http->uri); + err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST); + err->src_addr = conn->peer.sin_addr; + err->url = xstrdup(http->uri); + http->al.http.code = err->http_status; + http->entry = clientCreateStoreEntry(http, method, null_request_flags); + errorAppendEntry(http->entry, err); + safe_free(prefix); + break; + } else { + /* compile headers */ + /* we should skip request line! */ + if (!httpRequestParseHeader(request, prefix + req_line_sz)) + debug(33, 1) ("Failed to parse request headers: %s\n%s\n", + http->uri, prefix); + /* continue anyway? */ + } + request->flags.accelerated = http->flags.accel; + if (!http->flags.internal) { + if (internalCheck(strBuf(request->urlpath))) { + if (internalHostnameIs(request->host) && + request->port == ntohs(Config.Sockaddr.http->s.sin_port)) { + http->flags.internal = 1; + } else if (internalStaticCheck(strBuf(request->urlpath))) { + xstrncpy(request->host, internalHostname(), SQUIDHOSTNAMELEN); + request->port = ntohs(Config.Sockaddr.http->s.sin_port); + http->flags.internal = 1; + } + } + } + /* + * cache the Content-length value in request_t. + */ + request->content_length = httpHeaderGetInt(&request->header, + HDR_CONTENT_LENGTH); + request->flags.internal = http->flags.internal; + safe_free(prefix); + safe_free(http->log_uri); + http->log_uri = xstrdup(urlCanonicalClean(request)); + request->client_addr = conn->peer.sin_addr; + request->my_addr = conn->me.sin_addr; + request->my_port = ntohs(conn->me.sin_port); + request->http_ver = http->http_ver; + if (!urlCheckRequest(request)) { + ErrorState *err = errorCon(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED); + err->src_addr = conn->peer.sin_addr; + err->request = requestLink(request); + request->flags.proxy_keepalive = 0; + http->al.http.code = err->http_status; + http->entry = clientCreateStoreEntry(http, request->method, null_request_flags); + errorAppendEntry(http->entry, err); + break; + } + if (!clientCheckContentLength(request)) { + ErrorState *err = errorCon(ERR_INVALID_REQ, HTTP_LENGTH_REQUIRED); + err->src_addr = conn->peer.sin_addr; + err->request = requestLink(request); + http->al.http.code = err->http_status; + http->entry = clientCreateStoreEntry(http, request->method, null_request_flags); + errorAppendEntry(http->entry, err); + break; + } + http->request = requestLink(request); + clientSetKeepaliveFlag(http); + /* Do we expect a request-body? */ + if (request->content_length > 0) { + conn->body.size_left = request->content_length; + request->body_connection = conn; + /* Is it too large? */ + if (clientRequestBodyTooLarge(request->content_length)) { + ErrorState *err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE); + err->request = requestLink(request); + http->entry = clientCreateStoreEntry(http, + METHOD_NONE, null_request_flags); + errorAppendEntry(http->entry, err); + break; + } + } + clientAccessCheck(http); + continue; /* while offset > 0 && body.size_left == 0 */ + } else if (parser_return_code == 0) { + /* + * Partial request received; reschedule until parseHttpRequest() + * is happy with the input + */ + if (size >= Config.maxRequestHeaderSize) { + ErrorState *err; + /* The request is too large to handle */ + debug(33, 1) ("Request header is too large (%d bytes)\n", + (int) size); + debug(33, 1) ("Config 'request_header_max_size'= %d bytes.\n", + Config.maxRequestHeaderSize); + err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE); + http = parseHttpRequestAbort(conn, "error:request-too-large"); + /* add to the client request queue */ + for (H = &conn->chr; *H; H = &(*H)->next); + *H = http; + http->entry = clientCreateStoreEntry(http, METHOD_NONE, null_request_flags); + errorAppendEntry(http->entry, err); + return; + } + break; + } + } /* while offset > 0 && conn->body.size_left == 0 */ + ncomm_read(fh, clientReadRequest, conn); +} + +static void +clientReadRequest(filehandle *fh, IOBuf *in, int offset, int size, int error, void *cbdata) +{ + ConnStateData *conn = cbdata; + + kb_incr(&statCounter.client_http.kbytes_in, size); + + /* TODO: error, EOF (size == 0) */ + + if (conn->in) + IOBufAppend(conn->in, IOBufP(in), size); + else + conn->in = cbdataReference(in); + + clientReadRequest2(conn); +} + + +#if OLD_VERSION +static void clientReadRequest(int fd, void *data) { ConnStateData *conn = data; @@ -2821,7 +2913,7 @@ } conn->in.buf[conn->in.offset] = '\0'; /* Terminate the string */ if (nrequests == 0) - fd_note(conn->fd, "Reading next request"); + fd_note(conn->fh, "Reading next request"); /* Process request */ http = parseHttpRequest(conn, &method, @@ -2976,6 +3068,7 @@ } } } +#endif /* OLD_VERSION */ /* file_read like function, for reading body content */ void @@ -2987,7 +3080,7 @@ callback(buf, 0, cbdata); /* Signal end of body */ return; } - debug(33, 2) ("clientReadBody: start fd=%d body_size=%lu in.offset=%ld cb=%p req=%p\n", conn->fd, (unsigned long int) conn->body.size_left, (long int) conn->in.offset, callback, request); + debug(33, 2) ("clientReadBody: start fh=%p body_size=%lu size=%ld cb=%p req=%p\n", conn->fh, (unsigned long int) conn->body.size_left, (long int)IOBufSize(conn->in), callback, request); conn->body.callback = callback; conn->body.cbdata = cbdata; conn->body.buf = buf; @@ -3000,31 +3093,37 @@ static void clientProcessBody(ConnStateData * conn) { - int size; + int size, remaining; char *buf = conn->body.buf; void *cbdata = conn->body.cbdata; CBCB *callback = conn->body.callback; request_t *request = conn->body.request; /* Note: request is null while eating "aborted" transfers */ - debug(33, 2) ("clientProcessBody: start fd=%d body_size=%lu in.offset=%ld cb=%p req=%p\n", conn->fd, (unsigned long int) conn->body.size_left, (long int) conn->in.offset, callback, request); - if (conn->in.offset) { + debug(33, 2) ("clientProcessBody: start fh=%p body_size=%ld size=%ld cb=%p req=%p\n", conn->fh, (unsigned long int)conn->body.size_left, (long int)IOBufSize(conn->in), callback, request); + if (conn->in) { /* Some sanity checks... */ assert(conn->body.size_left > 0); - assert(conn->in.offset > 0); + assert(conn->in); assert(callback != NULL); assert(buf != NULL); /* How much do we have to process? */ - size = conn->in.offset; + size = IOBufSize(conn->in); if (size > conn->body.size_left) /* only process the body part */ size = conn->body.size_left; if (size > conn->body.bufsize) /* don't copy more than requested */ size = conn->body.bufsize; - xmemcpy(buf, conn->in.buf, size); + xmemcpy(buf, IOBufP(conn->in), size); conn->body.size_left -= size; /* Move any remaining data */ - conn->in.offset -= size; - if (conn->in.offset > 0) - xmemmove(conn->in.buf, conn->in.buf + size, conn->in.offset); + remaining = IOBufSize(conn->in) - size; + if (remaining) { + IOBuf *newbuf = IOBufCreate(IOBufP(conn->in)+size, remaining); + cbdataUnreference(conn->in); + conn->in = cbdataReference(newbuf); + cbdataUnreference(newbuf); + } else { + cbdataUnreference(conn->in); + } /* Remove request link if this is the last part of the body, as * clientReadRequest automatically continues to process next request */ if (conn->body.size_left <= 0 && request != NULL) @@ -3041,7 +3140,7 @@ callback(buf, size, cbdata); if (request != NULL) requestUnlink(request); /* Linked in clientReadBody */ - debug(33, 2) ("clientProcessBody: end fd=%d size=%d body_size=%lu in.offset=%ld cb=%p req=%p\n", conn->fd, size, (unsigned long int) conn->body.size_left, (long int) conn->in.offset, callback, request); + debug(33, 2) ("clientProcessBody: end fh=%p size=%d body_size=%ld remaining=%ld cb=%p req=%p\n", conn->fh, size, (unsigned long int) conn->body.size_left, (long int)IOBufSize(conn->in), callback, request); } } @@ -3051,9 +3150,9 @@ clientReadBodyAbortHandler(char *buf, size_t size, void *data) { ConnStateData *conn = (ConnStateData *) data; - debug(33, 2) ("clientReadBodyAbortHandler: fd=%d body_size=%lu in.offset=%ld\n", conn->fd, (unsigned long int) conn->body.size_left, (long int) conn->in.offset); + debug(33, 2) ("clientReadBodyAbortHandler: fh=%p body_size=%lu size=%ld\n", conn->fh, (unsigned long int) conn->body.size_left, (long int) IOBufSize(conn->in)); if (size != 0 && conn->body.size_left != 0) { - debug(33, 3) ("clientReadBodyAbortHandler: fd=%d shedule next read\n", conn->fd); + debug(33, 3) ("clientReadBodyAbortHandler: fh=%p shedule next read\n", conn->fh); conn->body.callback = clientReadBodyAbortHandler; conn->body.buf = bodyAbortBuf; conn->body.bufsize = sizeof(bodyAbortBuf); @@ -3089,6 +3188,7 @@ return 1; /* Aborted */ } +#if NOT_YET_PORTED /* general lifetime handler for HTTP requests */ static void requestTimeout(int fd, void *data) @@ -3096,7 +3196,7 @@ #if THIS_CONFUSES_PERSISTENT_CONNECTION_AWARE_BROWSERS_AND_USERS ConnStateData *conn = data; ErrorState *err; - debug(33, 3) ("requestTimeout: FD %d: lifetime is expired.\n", fd); + debug(33, 3) ("requestTimeout: FH %p: lifetime is expired.\n", fd); if (fd_table[fd].rwstate) { /* * Some data has been sent to the client, just close the FD @@ -3139,7 +3239,7 @@ * the open has already been completed on another * connection) */ - debug(33, 3) ("requestTimeout: FD %d: lifetime is expired.\n", fd); + debug(33, 3) ("requestTimeout: FH %p: lifetime is expired.\n", fd); comm_close(fd); #endif } @@ -3167,57 +3267,40 @@ } return 1; } +#endif /* NOT_YET_PORTED */ + /* Handle a new connection on HTTP socket. */ -void -httpAccept(int sock, void *data) +static void +clientNewHttpConnection(filehandle *fh, int error, struct sockaddr *local, struct sockaddr *peer, int addrlen, void *cbdata) { - int *N = &incoming_sockets_accepted; int fd = -1; - ConnStateData *connState = NULL; - struct sockaddr_in peer; - struct sockaddr_in me; - int max = INCOMING_HTTP_MAX; + ConnStateData *conn = NULL; #if USE_IDENT static aclCheck_t identChecklist; #endif - commSetSelect(sock, COMM_SELECT_READ, httpAccept, NULL, 0); - while (max-- && !httpAcceptDefer(sock, NULL)) { - memset(&peer, '\0', sizeof(struct sockaddr_in)); - memset(&me, '\0', sizeof(struct sockaddr_in)); - if ((fd = comm_accept(sock, &peer, &me)) < 0) { - if (!ignoreErrno(errno)) - debug(50, 1) ("httpAccept: FD %d: accept failure: %s\n", - sock, xstrerror()); - break; - } - debug(33, 4) ("httpAccept: FD %d: accepted\n", fd); - connState = cbdataAlloc(ConnStateData); - connState->peer = peer; - connState->log_addr = peer.sin_addr; - connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; - connState->me = me; - connState->fd = fd; - connState->in.size = CLIENT_REQ_BUF_SZ; - connState->in.buf = memAllocate(MEM_CLIENT_REQ_BUF); - /* XXX account connState->in.buf */ - comm_add_close_handler(fd, connStateFree, connState); - if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(peer.sin_addr, FQDN_LOOKUP_IF_MISS); - commSetTimeout(fd, Config.Timeout.request, requestTimeout, connState); + debug(33, 4) ("httpAccept: FH %p: accepted\n", fd); + conn = cbdataAlloc(ConnStateData); + conn->fh = cbdataReference(fh); + memcpy(&conn->peer, peer, sizeof(conn->peer)); /* addrsize? */ + conn->log_addr = ((struct sockaddr_in *)peer)->sin_addr; + conn->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; + memcpy(&conn->me, local, sizeof(conn->me)); /* addrsize? */ +#if NOT_YET_PORTED + comm_add_close_handler(fd, connFree, conn); + if (Config.onoff.log_fqdn) + fqdncache_gethostbyaddr(peer.sin_addr, FQDN_LOOKUP_IF_MISS); + commSetTimeout(fd, Config.Timeout.request, requestTimeout, conn); +#endif #if USE_IDENT - identChecklist.src_addr = peer.sin_addr; - identChecklist.my_addr = me.sin_addr; - identChecklist.my_port = ntohs(me.sin_port); - if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) - identStart(&me, &peer, clientIdentDone, connState); + identChecklist.src_addr = ((struct sockaddr_in *)peer)->sin_addr; + identChecklist.my_addr = ((struct sockaddr_in *)local)->sin_addr; + identChecklist.my_port = ntohs(((struct sockaddr_in *)local)->sin_port); + if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) + identStart(local, peer, clientIdentDone, conn); #endif - commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, connState, 0); - commSetDefer(fd, clientReadDefer, connState); - clientdbEstablished(peer.sin_addr, 1); - assert(N); - (*N)++; - } + clientdbEstablished(((struct sockaddr_in *)peer)->sin_addr, 1); + ncomm_read(fh, clientReadRequest, conn); } #if USE_SSL @@ -3464,35 +3547,13 @@ clientHttpConnectionsOpen(void) { sockaddr_in_list *s; - int fd; + filehandle *fh; for (s = Config.Sockaddr.http; s; s = s->next) { - if (MAXHTTPPORTS == NHttpSockets) { - debug(1, 1) ("WARNING: You have too many 'http_port' lines.\n"); - debug(1, 1) (" The limit is %d\n", MAXHTTPPORTS); - continue; - } enter_suid(); - fd = comm_open(SOCK_STREAM, - 0, - s->s.sin_addr, - ntohs(s->s.sin_port), - COMM_NONBLOCKING, - "HTTP Socket"); + fh = ncomm_listen_transparent(SOCK_STREAM, 0, (struct sockaddr *)&s->s, sizeof(s->s), 8192, clientNewHttpConnection, NULL); leave_suid(); - if (fd < 0) - continue; - comm_listen(fd); - commSetSelect(fd, COMM_SELECT_READ, httpAccept, NULL, 0); - /* - * We need to set a defer handler here so that we don't - * peg the CPU with select() when we hit the FD limit. - */ - commSetDefer(fd, httpAcceptDefer, NULL); - debug(1, 1) ("Accepting HTTP connections at %s, port %d, FD %d.\n", - inet_ntoa(s->s.sin_addr), - (int) ntohs(s->s.sin_port), - fd); - HttpSockets[NHttpSockets++] = fd; + if (fh == NULL) + fatal("Cannot open HTTP Port"); } } @@ -3546,7 +3607,7 @@ int i; for (i = 0; i < NHttpSockets; i++) { if (HttpSockets[i] >= 0) { - debug(1, 1) ("FD %d Closing HTTP connection\n", HttpSockets[i]); + debug(1, 1) ("FH %p Closing HTTP connection\n", HttpSockets[i]); comm_close(HttpSockets[i]); HttpSockets[i] = -1; } Index: squid/src/comm.c diff -u squid/src/comm.c:1.18 squid/src/comm.c:1.7.12.9 --- squid/src/comm.c:1.18 Wed Oct 24 02:42:12 2001 +++ squid/src/comm.c Sat Nov 17 05:11:58 2001 @@ -1,4 +1,3 @@ - /* * $Id$ * @@ -942,10 +941,31 @@ } /* a wrapper around comm_write to allow for MemBuf to be comm_written in a snap */ +typedef struct { + char **bufp; + CWCB *handler; + void *handler_data; +} comm_write_mbuf_handle; +CBDATA_TYPE(comm_write_mbuf_handle); +static void comm_write_mbuf_handler(int fd, char *buf, size_t size, int flag, void *data) +{ + comm_write_mbuf_handle *handle = data; + cbdataUnreference(handle->bufp); + if (cbdataValid(handle->handler_data)) + handle->handler(fd, NULL, size, flag, handle->handler_data); + cbdataUnreference(handle->handler_data); + cbdataFree(handle); +} void comm_write_mbuf(int fd, MemBuf mb, CWCB * handler, void *handler_data) { - comm_write(fd, mb.buf, mb.size, handler, handler_data, memBufFreeFunc(&mb)); + comm_write_mbuf_handle *handle; + CBDATA_INIT_TYPE(comm_write_mbuf_handle); + handle = cbdataAlloc(comm_write_mbuf_handle); + handle->bufp = cbdataReference(mb.bufp); + handle->handler = handler; + handle->handler_data = handler_data; + comm_write(fd, *handle->bufp, mb.size, comm_write_mbuf_handler, handle, NULL); } /* Index: squid/src/comm_select.c diff -u squid/src/comm_select.c:1.8 squid/src/comm_select.c:1.4.12.4 --- squid/src/comm_select.c:1.8 Wed Oct 24 02:42:12 2001 +++ squid/src/comm_select.c Sat Nov 17 05:11:58 2001 @@ -1,4 +1,3 @@ - /* * $Id$ * Index: squid/src/defines.h diff -u squid/src/defines.h:1.15 squid/src/defines.h:1.8.12.6 --- squid/src/defines.h:1.15 Sat Nov 17 17:15:42 2001 +++ squid/src/defines.h Wed Nov 21 18:19:01 2001 @@ -234,7 +234,7 @@ #define countof(arr) (sizeof(arr)/sizeof(*arr)) /* to initialize static variables (see also MemBufNull) */ -#define MemBufNULL { NULL, 0, 0, 0, NULL } +#define MemBufNULL { NULL, 0, 0, 0 } /* * Max number of ICP messages to receive per call to icpHandleUdp @@ -296,4 +296,9 @@ #define O_BINARY 0 #endif +/* IOBuf macros */ +#define IOBufP(iobuf) (*(iobuf)->bufp) +#define IOBufSize(iobuf) ((iobuf) ? (iobuf)->size : 0) +#define IOBufAppend(iobuf, buf, size) memBufAppend(iobuf, buf, size) + #endif /* SQUID_DEFINES_H */ Index: squid/src/disk.c diff -u squid/src/disk.c:1.8 squid/src/disk.c:1.5.12.6 --- squid/src/disk.c:1.8 Thu Aug 16 00:39:03 2001 +++ squid/src/disk.c Wed Sep 12 13:34:25 2001 @@ -1,4 +1,3 @@ - /* * $Id$ * @@ -331,10 +330,31 @@ * a wrapper around file_write to allow for MemBuf to be file_written * in a snap */ +typedef struct { + char **bufp; + DWCB *handler; + void *handler_data; +} file_write_mbuf_handle; +CBDATA_TYPE(file_write_mbuf_handle); +static void file_write_mbuf_handler(int fd, int errflag, size_t len, void *data) +{ + file_write_mbuf_handle *handle = data; + cbdataUnreference(handle->bufp); + if (cbdataValid(handle->handler_data)) + handle->handler(fd, errflag, len, handle->handler_data); + cbdataUnreference(handle->handler_data); + cbdataFree(handle); +} void file_write_mbuf(int fd, off_t off, MemBuf mb, DWCB * handler, void *handler_data) { - file_write(fd, off, mb.buf, mb.size, handler, handler_data, memBufFreeFunc(&mb)); + file_write_mbuf_handle *handle; + CBDATA_INIT_TYPE(file_write_mbuf_handle); + handle = cbdataAlloc(file_write_mbuf_handle); + handle->bufp = cbdataReference(mb.bufp); + handle->handler = handler; + handle->handler_data = handler_data; + file_write(fd, off, *handle->bufp, mb.size, file_write_mbuf_handler, handle, NULL); } /* Read from FD */ Index: squid/src/dlink.c diff -u /dev/null squid/src/dlink.c:1.1.2.1 --- /dev/null Tue Sep 28 18:37:31 2004 +++ squid/src/dlink.c Sat Feb 24 15:48:43 2001 @@ -0,0 +1,71 @@ +#include "squid.h" + +MemPool *dlink_node_pool = NULL; + +dlink_node * +dlinkNodeNew() +{ + if (dlink_node_pool == NULL) + dlink_node_pool = memPoolCreate("Dlink list nodes", sizeof(dlink_node)); + /* where should we call memPoolDestroy(dlink_node_pool); */ + return memPoolAlloc(dlink_node_pool); +} + +/* the node needs to be unlinked FIRST */ +void +dlinkNodeDelete(dlink_node * m) +{ + if (m == NULL) + return; + memPoolFree(dlink_node_pool, m); +} + +void +dlinkAdd(void *data, dlink_node * m, dlink_list * list) +{ + m->data = data; + m->prev = NULL; + m->next = list->head; + if (list->head) + list->head->prev = m; + list->head = m; + if (list->tail == NULL) + list->tail = m; +} + +void +dlinkAddTail(void *data, dlink_node * m, dlink_list * list) +{ + m->data = data; + m->next = NULL; + m->prev = list->tail; + if (list->tail) + list->tail->next = m; + list->tail = m; + if (list->head == NULL) + list->head = m; +} + +void +dlinkDelete(dlink_node * m, dlink_list * list) +{ + if (m->next) + m->next->prev = m->prev; + if (m->prev) + m->prev->next = m->next; + if (m == list->head) + list->head = m->next; + if (m == list->tail) + list->tail = m->prev; + m->next = m->prev = NULL; +} + +void * +dlinkGetFirst(dlink_list * list) +{ + dlink_node * m = list->head; + if (!m) + return NULL; + dlinkDelete(m, list); + return m->data; +} Index: squid/src/enums.h diff -u squid/src/enums.h:1.27 squid/src/enums.h:1.14.8.9 --- squid/src/enums.h:1.27 Sat Nov 17 17:15:42 2001 +++ squid/src/enums.h Wed Nov 21 18:19:01 2001 @@ -720,6 +720,15 @@ } cbdata_type; /* + * comm_server stuff + */ +enum comm_event_type { + EVENT_NONE, + EVENT_READ, + EVENT_WRITE +}; + +/* * Return codes from checkVary(request) */ enum { Index: squid/src/errorpage.c diff -u squid/src/errorpage.c:1.15 squid/src/errorpage.c:1.10.12.4 --- squid/src/errorpage.c:1.15 Wed Oct 24 02:42:12 2001 +++ squid/src/errorpage.c Sat Nov 17 05:11:58 2001 @@ -515,7 +515,7 @@ MemBuf sign_mb; err->page_id = ERR_SQUID_SIGNATURE; sign_mb = errorBuildContent(err); - memBufPrintf(&mb, "%s", sign_mb.buf); + memBufPrintf(&mb, "%s", *sign_mb.bufp); memBufClean(&sign_mb); err->page_id = saved_id; do_quote = 0; @@ -553,7 +553,7 @@ break; } if (!p) - p = mb.buf; /* do not use mb after this assignment! */ + p = *mb.bufp; /* do not use mb after this assignment! */ assert(p); debug(4, 3) ("errorConvert: %%%c --> '%s'\n", token, p); if (do_quote) @@ -606,6 +606,6 @@ } if (*m) memBufPrintf(&content, "%s", m); /* copy tail */ - assert(content.size == strlen(content.buf)); + assert(content.size == strlen(*content.bufp)); return content; } Index: squid/src/fd.c diff -u squid/src/fd.c:1.7 squid/src/fd.c:1.5.12.4 --- squid/src/fd.c:1.7 Sun Aug 26 15:26:29 2001 +++ squid/src/fd.c Wed Sep 12 13:49:10 2001 @@ -84,13 +84,9 @@ assert(F->write_handler == NULL); } debug(51, 3) ("fd_close FD %d %s\n", fd, F->desc); - F->flags.open = 0; + memset(F, '\0', sizeof(fde)); fdUpdateBiggest(fd, 0); Number_FD--; - commUpdateReadBits(fd, NULL); - commUpdateWriteBits(fd, NULL); - memset(F, '\0', sizeof(fde)); - F->timeout = 0; } int Index: squid/src/forward.c diff -u squid/src/forward.c:1.13 squid/src/forward.c:1.9.12.3 --- squid/src/forward.c:1.13 Wed Oct 10 11:07:43 2001 +++ squid/src/forward.c Sat Nov 17 05:11:58 2001 @@ -431,8 +431,8 @@ request_t *request = fwdState->request; StoreEntry *entry = fwdState->entry; ErrorState *err; - debug(17, 3) ("fwdDispatch: FD %d: Fetching '%s %s'\n", - fwdState->client_fd, + debug(17, 3) ("fwdDispatch: FH %p: Fetching '%s %s'\n", + fwdState->client_fh, RequestMethodStr[request->method], storeUrl(entry)); /*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */ @@ -546,7 +546,7 @@ } void -fwdStart(int fd, StoreEntry * e, request_t * r) +fwdStart(filehandle *fh, StoreEntry * e, request_t * r) { FwdState *fwdState; aclCheck_t ch; @@ -577,7 +577,6 @@ } debug(17, 3) ("fwdStart: '%s'\n", storeUrl(e)); e->mem_obj->request = requestLink(r); - e->mem_obj->fd = fd; #if URL_CHECKSUM_DEBUG assert(e->mem_obj->chksum == url_checksum(e->mem_obj->url)); #endif @@ -596,7 +595,7 @@ internalStart(r, e); return; case PROTO_CACHEOBJ: - cachemgrStart(fd, r, e); + cachemgrStart(r, e); return; case PROTO_URN: urnStart(r, e); @@ -606,7 +605,7 @@ } fwdState = cbdataAlloc(FwdState); fwdState->entry = e; - fwdState->client_fd = fd; + fwdState->client_fh = fh; fwdState->server_fd = -1; fwdState->request = requestLink(r); fwdState->start = squid_curtime; Index: squid/src/gopher.c diff -u squid/src/gopher.c:1.10 squid/src/gopher.c:1.7.12.3 --- squid/src/gopher.c:1.10 Wed Oct 24 02:42:13 2001 +++ squid/src/gopher.c Sat Nov 17 05:11:58 2001 @@ -187,7 +187,7 @@ } memBufPrintf(&mb, "\r\n"); EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT); - storeAppend(gopherState->entry, mb.buf, mb.size); + storeAppend(gopherState->entry, *mb.bufp, mb.size); memBufClean(&mb); } Index: squid/src/http.c diff -u squid/src/http.c:1.17 squid/src/http.c:1.11.12.6 --- squid/src/http.c:1.17 Wed Oct 24 02:42:13 2001 +++ squid/src/http.c Sat Nov 17 05:11:58 2001 @@ -964,12 +964,16 @@ else sendHeaderDone = httpSendComplete; +#if NOT_YET_PORTED if (!opt_forwarded_for) cfd = -1; else if (entry->mem_obj == NULL) cfd = -1; else cfd = entry->mem_obj->fd; +#else + cfd = -1; +#endif assert(-1 == cfd || FD_SOCKET == fd_table[cfd].type); if (p != NULL) httpState->flags.proxying = 1; @@ -997,7 +1001,7 @@ &mb, cfd, httpState->flags); - debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", httpState->fd, mb.buf); + debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", httpState->fd, *mb.bufp); comm_write_mbuf(httpState->fd, mb, sendHeaderDone, httpState); } Index: squid/src/ident.c diff -u squid/src/ident.c:1.8 squid/src/ident.c:1.6.12.3 --- squid/src/ident.c:1.8 Fri Apr 13 17:31:02 2001 +++ squid/src/ident.c Sat Apr 14 06:43:18 2001 @@ -186,8 +186,10 @@ * start a TCP connection to the peer host on port 113 */ void -identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data) +identStart(struct sockaddr *local, struct sockaddr *remote, IDCB * callback, void *data) { + struct sockaddr_in *me = (struct sockaddr_in *)local; + struct sockaddr_in *my_peer = (struct sockaddr_in *)remote; IdentStateData *state; int fd; char key1[IDENT_KEY_SZ]; Index: squid/src/internal.c diff -u squid/src/internal.c:1.7 squid/src/internal.c:1.7.12.1 --- squid/src/internal.c:1.7 Fri Jan 12 00:20:33 2001 +++ squid/src/internal.c Sat Feb 24 04:52:42 2001 @@ -117,7 +117,7 @@ memBufPrintf(&mb, "%s", dir); memBufPrintf(&mb, "%s", name); /* return a pointer to a local static buffer */ - return mb.buf; + return *mb.bufp; } /* Index: squid/src/main.c diff -u squid/src/main.c:1.28 squid/src/main.c:1.19.8.8 --- squid/src/main.c:1.28 Wed Oct 24 02:42:13 2001 +++ squid/src/main.c Sat Nov 17 05:11:58 2001 @@ -645,8 +645,11 @@ if (checkRunningPid()) exit(1); + memBuf_module_init(); + #if TEST_ACCESS comm_init(); + ncomm_module_init(); comm_select_init(); mainInitialize(); test_access(); @@ -682,6 +685,7 @@ /* init comm module */ comm_init(); + ncomm_module_init(); comm_select_init(); if (opt_no_daemon) { @@ -720,6 +724,7 @@ eventRun(); if ((loop_delay = eventNextTime()) < 0) loop_delay = 0; + ncomm_handle_events(0); #if HAVE_POLL switch (comm_poll(loop_delay)) { #else Index: squid/src/mem.c diff -u squid/src/mem.c:1.13 squid/src/mem.c:1.8.12.4 --- squid/src/mem.c:1.13 Fri Sep 7 16:55:49 2001 +++ squid/src/mem.c Wed Sep 12 13:34:25 2001 @@ -65,6 +65,7 @@ /* local routines */ +#if 0 static void memStringStats(StoreEntry * sentry) { @@ -102,7 +103,7 @@ memStringStats(sentry); storeBufferFlush(sentry); } - +#endif /* * public routines @@ -247,9 +248,11 @@ for (i = 0; i < mem_str_pool_count; i++) { StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size); } +#if 0 cachemgrRegister("mem", "Memory Utilization", memStats, 0, 1); +#endif } /* Index: squid/src/mime.c diff -u squid/src/mime.c:1.11 squid/src/mime.c:1.8.12.4 --- squid/src/mime.c:1.11 Tue Nov 13 14:19:33 2001 +++ squid/src/mime.c Sat Nov 17 05:11:58 2001 @@ -409,7 +409,7 @@ if (storeGetPublic(url, METHOD_GET)) return; snprintf(path, MAXPATHLEN, "%s/%s", Config.icons.directory, icon); - fd = file_open(path, O_RDONLY | O_BINARY); + fd = open(path, O_RDONLY | O_BINARY, 0); if (fd < 0) { debug(25, 0) ("mimeLoadIconFile: %s: %s\n", path, xstrerror()); return; @@ -443,7 +443,7 @@ buf = memAllocate(MEM_4K_BUF); while ((n = FD_READ_METHOD(fd, buf, 4096)) > 0) storeAppend(e, buf, n); - file_close(fd); + close(fd); storeBufferFlush(e); storeComplete(e); storeTimestampsSet(e); Index: squid/src/ncomm.c diff -u /dev/null squid/src/ncomm.c:1.1.2.17 --- /dev/null Tue Sep 28 18:37:31 2004 +++ squid/src/ncomm.c Wed Nov 21 18:32:12 2001 @@ -0,0 +1,804 @@ +#include "squid.h" +#include "ncomm_internals.h" + +/* transparent proxying requires some extra headers... */ + +#if IPF_TRANSPARENT +#if HAVE_SYS_IOCTL_H +#include +#endif +#include +#include +#if HAVE_IP_FIL_COMPAT_H +#include +#elif HAVE_NETINET_IP_FIL_COMPAT_H +#include +#elif HAVE_IP_COMPAT_H +#include +#elif HAVE_NETINET_IP_COMPAT_H +#include +#endif +#if HAVE_IP_FIL_H +#include +#elif HAVE_NETINET_IP_FIL_H +#include +#endif +#if HAVE_IP_NAT_H +#include +#elif HAVE_NETINET_IP_NAT_H +#include +#endif +#endif + +#if LINUX_NETFILTER +#include +#endif + +/* end of headers for transparent proxying */ + + +#define UNUSED __attribute__((unused)) + +typedef enum cbent_type { + COMMCB_none, + COMMCB_io, + COMMCB_new, + COMMCB_close +} cbent_type_t; + +typedef struct { + dlink_node node; + cbent_type_t type; + filehandle *fh; + void *cbdata; + int error; + union { + struct { + COMMIOCB *callback; + IOBuf *buf; + size_t offset; + ssize_t len; + } io; + struct { + COMMNEWCB *callback; + } new; + struct { + COMMCLOSECB *callback; + } close; + } cb; +} comm_callback_entry_t; + +dlink_list callbacklist; +CBDATA_TYPE(comm_callback_entry_t); +CBDATA_TYPE(filehandle); +CBDATA_TYPE(IOBuf); +CBDATA_TYPE(fh_write_t); + +static void +IOBufIsFreed(void *data) +{ + IOBuf *buf = data; + memBufClean(buf); +} + +IOBuf * +IOBufAlloc(size_t size) +{ + IOBuf *buf, *bufp; + buf = cbdataAlloc(IOBuf); + memBufInit(buf, size, 1024*1024); /* max 1MB per IOBuf */ + bufp = cbdataReference(buf); + cbdataFree(buf); + return bufp; +} + +IOBuf * +IOBufCreate(void *data, size_t size) +{ + IOBuf *buf = IOBufAlloc(size); + memBufAppend(buf, data, size); + return buf; +} + +IOBuf * +IOBufCreateFromMemBuf(MemBuf *mb) +{ + IOBuf *buf; + buf = cbdataAlloc(IOBuf); + *buf = *mb; + mb->bufp = NULL; + return buf; +} + +static int +ncommIgnoreErrno(int error) +{ + switch (error) { + case EINPROGRESS: + case EWOULDBLOCK: +#if EAGAIN != EWOULDBLOCK + case EAGAIN: +#endif + case EALREADY: + case EINTR: +#ifdef ERESTART + case ERESTART: +#endif + return 1; + default: + return 0; + } +} + +static comm_callback_entry_t * +newCbent(filehandle *fh, int error, void *cbdata, cbent_type_t type) +{ + comm_callback_entry_t *cbent = cbdataAlloc(comm_callback_entry_t); + cbent->fh = cbdataReference(fh); + cbent->type = type; + cbent->error = error; + cbent->cbdata = cbdataReference(cbdata); + return cbent; +} + +static void +comm_new_callback(filehandle *fh, int error, COMMNEWCB *callback, void *cbdata) +{ + comm_callback_entry_t *cbent = newCbent(fh, error, cbdata, COMMCB_new); + cbent->cb.new.callback = callback; + + dlinkAddTail(cbent, &cbent->node, &callbacklist); +} + +static void +comm_io_callback(filehandle *fh, IOBuf *buf, size_t offset, ssize_t len, int error, COMMIOCB *callback, void *cbdata) +{ + comm_callback_entry_t *cbent = newCbent(fh, error, cbdata, COMMCB_io); + cbent->cb.io.callback = callback; + cbent->cb.io.buf = cbdataReference(buf); + cbent->cb.io.offset = offset; + cbent->cb.io.len = len; + + dlinkAddTail(cbent, &cbent->node, &callbacklist); +} + +#if NOT_YET_USED +static void +comm_close_callback(filehandle *fh, int error, COMMNEWCB *callback, void *cbdata) +{ + comm_callback_entry_t *cbent = newCbent(fh, error, cbdata, COMMCB_new); + cbent->cb.new.callback = callback; + + dlinkAddTail(cbent, &cbent->node, &callbacklist); +} +#endif + +void +ncomm_call_callbacks(void) +{ + /* Do callbacks */ + comm_callback_entry_t *cb; + while((cb = dlinkGetFirst(&callbacklist)) != NULL) { + int valid = cbdataValid(cb->cbdata); + filehandle *fh = cb->fh; + switch(cb->type) { + case COMMCB_io: + if (valid && cb->cb.io.callback) + cb->cb.io.callback(fh, cb->cb.io.buf, cb->cb.io.offset, cb->cb.io.len, cb->error, cb->cbdata); + cbdataUnreference(cb->cb.io.buf); + break; + case COMMCB_new: + if (valid && cb->cb.new.callback) { + if (fh) + cb->cb.new.callback(fh, cb->error, &fh->local, &fh->peer, fh->addrsize, cb->cbdata); + else + cb->cb.new.callback(NULL, cb->error, NULL, NULL, 0, cb->cbdata); + } + break; + case COMMCB_close: + /* NOT YET DONE */ + break; + default: + fatal("Unknown ncomm callback type"); + break; + } + cbdataUnreference(cb->cbdata); + cbdataUnreference(cb->fh); + cbdataFree(cb); + } +} + +static void +comm_read_callback(filehandle *fh, fh_read_t *fhr, void *data, int len, int error) +{ + COMMIOCB *callback = fhr->callback; + void *cbdata; + IOBuf *buf = NULL; + fhr->callback = NULL; + if (len > 0) + buf = IOBufCreate(data, len); + cbdata = cbdataEatReference(fhr->cbdata); + comm_io_callback(fh, buf, 0, len, error, callback, cbdata); + cbdataUnreference(cbdata); + cbdataUnreference(buf); +} + +static void +fh_bytes(filehandle *fh, ssize_t len, unsigned int type) +{ +} + +static void +fh_open(filehandle *fh, const char *descr) +{ +} + +static void +comm_do_close(filehandle *fh) +{ + if (!fh->shutdown_write) { + shutdown(fh->fd, 1); + fh->shutdown_write = 1; + } + if (fh->shutdown_read) { + close(fh->fd); + fh->fd = -1; + } +} + +static int +comm_do_read(filehandle *fh) +{ + static char inbuf[65536]; + int fd = fh->fd; + fh_read_t *fhr = &fh->read; + /* Read in some data */ + const ssize_t len = read(fd, inbuf, fhr->size); + statCounter.syscalls.sock.reads++; + fh_bytes(fh, len, FD_READ); + if (len > 0) { + /* We got some data to deliver to the application */ + comm_read_callback(fh, fhr, inbuf, len, 0); + return 1; + } else if (len == 0 || (len == -1 && !ncommIgnoreErrno(errno))) { + int saved_errno = errno; + /* EOF or error, shut down the read channel */ + fh->shutdown_read = 1; + if (fh->shutdown_write) { + close(fh->fd); + fh->fd = -1; + } else { + shutdown(fh->fd, 0); + } + comm_read_callback(fh, fhr, NULL, len, len ? saved_errno : 0); + return 1; + } + /* Try again */ + return 0; +} + +void +ncomm_read_limited(filehandle *fh, size_t size, COMMIOCB *callback, void *cbdata) +{ + fh_read_t *fhr = &fh->read; + int done; + + if (size > 65536) + size = 65536; /* Do not overflow buffer in comm_do_read */ + + /* Read in some data */ + fhr->size = size; + fhr->callback = callback; + fhr->cbdata = cbdataReference(cbdata); + done = comm_do_read(fh); + if (!done) { + /* Oops.. we could not get any data. Register for read event */ + comm_register_for_read_event(fh, comm_do_read); + } +} + +void +ncomm_read(filehandle *fh, COMMIOCB *callback, void *cbdata) +{ + ncomm_read_limited(fh, 65536, callback, cbdata); +} + +static void +comm_write_callback(filehandle *fh, fh_write_t *fhw, int len, int error) +{ + COMMIOCB *callback = fhw->callback; + void *cbdata; + IOBuf *buf; + fhw->callback = NULL; + cbdata = cbdataEatReference(fhw->cbdata); + buf = cbdataEatReference(fhw->buf); + comm_io_callback(fh, buf, fhw->offset, len, error, callback, cbdata); + cbdataUnreference(cbdata); + cbdataUnreference(buf); +} + +static int +comm_do_write(filehandle *fh) +{ + fh_write_t *fhw; + int fd = fh->fd; + /* Write out some more data */ + const void *buf; + size_t size = fhw->size - fhw->done; + ssize_t len; +writemore: + fhw = fh->write; + buf = (void *)(*fhw->buf->bufp + fhw->done); + size = fhw->size - fhw->done; + assert(size > 0); + len = write(fd, buf, size); + statCounter.syscalls.sock.writes++; + fh_bytes(fh, len, FD_WRITE); + if ((size_t)len == size) { + /* finished */ + fh->write = fhw->next; + comm_write_callback(fh, fhw, (ssize_t)fhw->size, 0); + cbdataFree(fhw); + if (fh->write) + goto writemore; + /* OK. No more data. We are done */ + if (fh->closed) + comm_do_close(fh); + return 1; + } + if (len == -1 && !ncommIgnoreErrno(errno)) { + /* error */ + comm_write_callback(fh, fhw, fhw->done, errno); + if (fh->closed) + comm_do_close(fh); + return 1; + } + /* try again */ + if (len > 0) + fhw->done += len; + return 0; +} + +void +ncomm_write_fragment(filehandle *fh, IOBuf *buf, size_t offset, size_t size, COMMIOCB *callback, void *cbdata) +{ + int done; + int first = 1; + fh_write_t **fhwp; + fh_write_t *fhw = cbdataAlloc(fh_write_t); + fhw->buf = cbdataReference(buf); + fhw->offset = offset; + fhw->size = size; + fhw->done = 0; + fhw->callback = callback; + fhw->cbdata = cbdataReference(cbdata); + for (fhwp = &fh->write; *fhwp; fhwp = &(*fhwp)->next) + first = 0; + *fhwp = fhw; + if (first) + done = comm_do_write(fh); + else + done = 0; /* there is pending writes ahead of this one... */ + if (!done) + comm_register_for_write_event(fh, comm_do_write); +} + +void +ncomm_write(filehandle *fh, IOBuf *buf, COMMIOCB *callback, void *cbdata) +{ + ncomm_write_fragment(fh, buf, 0, buf->size, callback, cbdata); +} + +/* a wrapper around comm_write to allow for MemBuf to be comm_written in a snap +*/ +void +ncomm_write_mbuf(filehandle *fh, MemBuf mb, COMMIOCB * callback, void *cbdata) +{ + IOBuf *buf = IOBufCreateFromMemBuf(&mb); + ncomm_write(fh, buf, callback, cbdata); +} + +static int +ncommSetNonBlocking(int fd) +{ + int flags; + int dummy = 0; + if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) { + debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror()); + return COMM_ERROR; + } + if (fcntl(fd, F_SETFL, flags | SQUID_NONBLOCK) < 0) { + debug(50, 0) ("commSetNonBlocking: FD %d: %s\n", fd, xstrerror()); + return COMM_ERROR; + } + return 0; +} + +static void +ncommSetCloseOnExec(int fd) +{ +#ifdef FD_CLOEXEC + int flags; + int dummy = 0; + if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) { + debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror()); + return; + } + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) + debug(50, 0) ("FD %d: set close-on-exec failed: %s\n", fd, xstrerror()); +#endif +} + +static int +comm_do_listen(filehandle *fh) +{ + int fd = fh->fd; + while(1) { + filehandle *nfh; + int nfd; + struct sockaddr saddr; + socklen_t addrsize = sizeof(saddr); + nfd = accept(fd, &saddr, &addrsize); + statCounter.syscalls.sock.accepts++; + if (nfd < 0) + break; + + nfh = cbdataAlloc(filehandle); + nfh->fd = nfd; + + /* Update the FD state */ + fh_open(nfh, "Incoming connection"); + + /* Update the socket information */ + memcpy(&nfh->peer, &saddr, addrsize); + nfh->addrsize = addrsize; + + addrsize = sizeof(nfh->local); + getsockname(nfd, (struct sockaddr *) &nfh->local, &addrsize); + if (addrsize < nfh->addrsize) + nfh->addrsize = addrsize; + +#if IPF_TRANSPARENT + if (fh->transparent && fh->local.sa_family == AF_INET) { + struct natlookup natLookup; + static int natfd = -1; + static const int siocgnatl_cmd = SIOCGNATL & 0xff; + int x; + struct sockaddr_in *local = (struct sockaddr_in *)&fh->local; + struct sockaddr_in *peer = (struct sockaddr_in *)&fh->peer; + + natLookup.nl_inport = local->sin_port; + natLookup.nl_outport = peer->sin_port; + natLookup.nl_inip = local->sin_addr; + natLookup.nl_outip = peer->sin_addr; + natLookup.nl_flags = IPN_TCP; + if (natfd < 0) + natfd = open(IPL_NAT, O_RDONLY, 0); + if (natfd < 0) { + debug(50, 1) ("WARNING: NAT open failed: %s\n", xstrerror()); + } else { + /* + * IP-Filter changed the type for SIOCGNATL between + * 3.3 and 3.4. It also changed the cmd value for + * SIOCGNATL, so at least we can detect it. We could + * put something in configure and use ifdefs here, but + * this seems simpler. + */ + if (63 == siocgnatl_cmd) { + struct natlookup *nlp = &natLookup; + x = ioctl(natfd, SIOCGNATL, &nlp); + } else { + x = ioctl(natfd, SIOCGNATL, &natLookup); + } + if (x < 0) { + if (errno != ESRCH) { + debug(50, 1) ("parseHttpRequest: NAT lookup failed: ioctl(SIOCGNATL)\n"); + close(natfd); + natfd = -1; + } + } else { + local->sin_port = natLookup.nl_realport; + local->sin_addr = natLookup.nl_realip; + nfh->transparent = 1; + } + } + } +#elsif LINUX_NETFILTER + if (fh->transparent) { + int x; + addrsize = sizeof(fh->local); + x = getsockopt(fh->fd, SOL_IP, SO_ORIGINAL_DST, &fh->local, &addrsize); + if (x == 0) + nfh->transparent = 1; + } +#endif + + /* Set the flags */ + ncommSetCloseOnExec(nfd); + ncommSetNonBlocking(nfd); + + /* Finally, hand over the socket */ + comm_new_callback(nfh, 0, fh->connect.callback, fh->connect.cbdata); + cbdataUnreference(fh->connect.cbdata); + } + if (!ncommIgnoreErrno(errno)) { + comm_new_callback(NULL, errno, fh->connect.callback, fh->connect.cbdata); + cbdataUnreference(fh->connect.cbdata); + } + /* continue listening */ + return 0; +} + +filehandle * +ncomm_listen(int sock_type, int proto, struct sockaddr *where, + int addrsize, int backlog, COMMNEWCB *callback, void *cbdata) +{ + filehandle *fh; + int fd, rc; + int on = 1; + + fd = socket(where->sa_family, sock_type, proto); + statCounter.syscalls.sock.sockets++; + if (fd < 0) + return NULL; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); + ncommSetCloseOnExec(fd); + ncommSetNonBlocking(fd); + rc = bind(fd, where, addrsize); + statCounter.syscalls.sock.binds++; + if (rc < 0) { + int saved_errno = errno; + close(fd); + statCounter.syscalls.sock.closes++; + errno = saved_errno; + return NULL; + } + rc = listen(fd, backlog); + if (rc < 0) { + int saved_errno = errno; + close(fd); + statCounter.syscalls.sock.closes++; + errno = saved_errno; + return NULL; + } + fh = cbdataAlloc(filehandle); + fh->fd = fd; + fh->local = *where; + fh->connect.callback = callback; + fh->connect.cbdata = cbdataReference(cbdata); + fh_open(fh, "Listening socket"); + comm_register_for_read_event(fh, comm_do_listen); + return fh; +} + +filehandle * +ncomm_listen_transparent(int sock_type, int proto, struct sockaddr *where, + int addrsize, int backlog, COMMNEWCB *callback, void *cbdata) +{ + filehandle *fh = ncomm_listen(sock_type, proto, where, addrsize, + backlog, callback, cbdata); + if (fh) + fh->transparent = 1; + + return fh; +} + +static void +destroy_filehandle(void *data) +{ + filehandle *fh = data; + if (fh->fd != -1) { + close(fh->fd); + fh->fd = -1; + } +} + +static void +destroy_fh_write(void *data) +{ + fh_write_t *fhw = data; + cbdataUnreference(fhw->buf); +} + +void +ncomm_module_init(void) +{ + CBDATA_INIT_TYPE(comm_callback_entry_t); + CBDATA_INIT_TYPE_FREECB(filehandle, destroy_filehandle); + CBDATA_INIT_TYPE_FREECB(IOBuf, IOBufIsFreed); + CBDATA_INIT_TYPE_FREECB(fh_write_t, destroy_fh_write); +} + +void ncomm_module_shutdown(void) +{ +} + + +void +ncomm_close(filehandle *fh) +{ + fh->closed = 1; + if (!fh->write && fh->fd != -1) + comm_do_close(fh); + cbdataFree(fh); +} + +int +ncomm_closed(filehandle *fh) +{ + return fh->closed; +} + +void +ncomm_abort(filehandle *fh) +{ + /* NOT YET IMPLEMENTED */ +} + +filehandle * +ncomm_accept(int sock_type, int proto, struct sockaddr *where, + struct sockaddr *from, int addrsize, + COMMNEWCB callback, void *cbdata) +{ + /* NOT YET IMPLEMENTED */ + return NULL; +} + +static int +comm_do_connect(filehandle *fh) +{ + int x; + int done = 0; + int err; + int errlen = sizeof(err); + x = connect(fh->fd, &fh->peer, sizeof(fh->peer)); + statCounter.syscalls.sock.connects++; + if (x == 0) { + errno = 0; + } else if (x < 0) { + debug(5, 9) ("connect FD %d: %s\n", fh->fd, xstrerror()); + } else { +#if defined(_SQUID_NEWSOS6_) + /* Makoto MATSUSHITA */ + x = connect(fh->fd, &fh->peer, sizeof(fh->peer)); + if (errno == EINVAL) { + errlen = sizeof(err); + x = getsockopt(fh->fd, SOL_SOCKET, SO_ERROR, &err, &errlen); + if (x >= 0) + errno = x; + } +#else + errlen = sizeof(err); + x = getsockopt(fh->fd, SOL_SOCKET, SO_ERROR, &err, &errlen); + if (x == 0) + errno = err; +#if defined(_SQUID_SOLARIS_) + /* + * Solaris 2.4's socket emulation doesn't allow you + * to determine the error from a failed non-blocking + * connect and just returns EPIPE. Create a fake + * error message for connect. -- fenner@parc.xerox.com + */ + if (x < 0 && errno == EPIPE) + errno = ENOTCONN; +#endif +#endif + } + if (errno == 0 || errno == EISCONN) { + errno = 0; + done = 1; + } else if (!ncommIgnoreErrno(errno)) { + done = 1; + } + if (done) { + socklen_t addrsize = sizeof(fh->local); + err = errno; /* just in case */ + getsockname(fh->fd, &fh->local, &addrsize); + if (addrsize < fh->addrsize) + fh->addrsize = addrsize; + if (err) { + comm_new_callback(fh, err, fh->connect.callback, fh->connect.cbdata); + cbdataUnreference(fh->connect.cbdata); + cbdataFree(fh); + } else { + comm_new_callback(fh, 0, fh->connect.callback, fh->connect.cbdata); + cbdataUnreference(fh->connect.cbdata); + } + } + return done; +} + +/* + * Open a new socket to a given service + */ +filehandle * +ncomm_connect(int sock_type, int proto, const struct sockaddr *local, const struct sockaddr *remote, int addrsize, COMMNEWCB *callback, void *cbdata) +{ + filehandle *fh; + int sock; + int x; + int done; + assert(remote); + sock = socket(remote->sa_family, sock_type, proto); + statCounter.syscalls.sock.sockets++; + if (sock == -1) { + debug(5, 1) ("comm_connet: Cannot create new socket: %s\n", xstrerror()); + return NULL; + } + ncommSetCloseOnExec(sock); + ncommSetNonBlocking(sock); + /* Bind to local endpoint */ + if (local) { + int on = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); + x = bind(sock, local, addrsize); + statCounter.syscalls.sock.binds++; + if (x != 0) + debug(5, 1) ("comm_connect: WARNING: Failed to bind local endpoint: %s\n", xstrerror()); + } + /* set up filehandle */ + fh = cbdataAlloc(filehandle); + fh->fd = sock; + if (local) + memcpy(&fh->local, local, addrsize); + memcpy(&fh->peer, remote, addrsize); + fh->addrsize = addrsize; + fh->peer = *remote; + fh->connect.callback = callback; + fh->connect.cbdata = cbdataReference(cbdata); + + /* Establish connection. */ + cbdataLock(fh); + done = comm_do_connect(fh); + + if (done) { + /* Ouch.. an error occurred while setting up the connection */ + cbdataUnlock(fh); + return NULL; + } + + if (!done) { + comm_register_for_write_event(fh, comm_do_connect); + } else if (!cbdataValid(fh)) { + /* Ouch.. an error occurred */ + cbdataUnlock(fh); + return NULL; + } + cbdataUnlock(fh); + return fh; +} + +int +ncomm_add_close_handler(filehandle *fh, COMMCLOSECB *handler, void *cbdata) +{ + /* NOT YET IMPLEMENTED */ + return 1; +} + +void +ncomm_note(filehandle *fh, const char *note) +{ + fd_note(fh->fd, note); +} + +int +ncomm_sendto(filehandle *fh, const struct sockaddr *to_addr, int addr_len, const void *msg, int msglen) +{ + int error = 0; + int x; + + x = sendto(fh->fd, msg, msglen, 0, to_addr, addr_len); + if (x < 0) { + error = errno; +#ifdef _SQUID_LINUX + if (errno != ECONNREFUSED) +#endif + debug(50, 1) ("ncomm_sendto: FH %p, %s, port %d: %s\n", + fh, + inet_ntoa(((struct sockaddr_in *)to_addr)->sin_addr), + (int) htons(((struct sockaddr_in *)to_addr)->sin_port), + xstrerror()); + return error; + } + return x; +} Index: squid/src/ncomm_internals.h diff -u /dev/null squid/src/ncomm_internals.h:1.1.2.6 --- /dev/null Tue Sep 28 18:37:31 2004 +++ squid/src/ncomm_internals.h Wed Nov 21 18:16:29 2001 @@ -0,0 +1,52 @@ +/* + * ncomm.c <-> ncomm_poll.c only + */ + +/* Execute queued callbacks */ +extern void ncomm_call_callbacks(void); + +/* event callbacks */ +typedef int COMMEVENTREAD(filehandle *fh); +typedef int COMMEVENTWRITE(filehandle *fh); + +/* event registration */ +void comm_register_for_read_event(filehandle *fh, COMMEVENTREAD *handler); +void comm_register_for_write_event(filehandle *fh, COMMEVENTWRITE *handler); + +/* internal filehandle structure */ +typedef struct { + size_t size; + COMMIOCB *callback; + void *cbdata; +} fh_read_t; +typedef struct _fh_write fh_write_t; +struct _fh_write { + fh_write_t *next; + IOBuf *buf; + size_t offset; + size_t size; + size_t done; + COMMIOCB *callback; + void *cbdata; +}; +typedef struct { + void *cbdata; + COMMNEWCB *callback; +} fh_connect_t; +struct _file_handle { + int fd; + fh_read_t read; + fh_write_t *write; + fh_connect_t connect; + void *eventdata; + socklen_t addrsize; + struct sockaddr peer; + struct sockaddr local; + COMMEVENTREAD *read_handler; + COMMEVENTWRITE *write_handler; + unsigned int closed:1; + unsigned int shutdown_read:1; + unsigned int shutdown_write:1; + unsigned int transparent:1; /* look up the real destination in NAT */ +}; + Index: squid/src/ncomm_poll.c diff -u /dev/null squid/src/ncomm_poll.c:1.1.2.3 --- /dev/null Tue Sep 28 18:37:31 2004 +++ squid/src/ncomm_poll.c Sat Feb 24 17:15:32 2001 @@ -0,0 +1,139 @@ +#include "squid.h" +#include "ncomm_internals.h" + +/* + * Magics for poll(2) + */ +static struct pollfd pollfds[FD_SETSIZE]; +static filehandle *pollfh[FD_SETSIZE]; +static unsigned int pollnfds = 0; +static unsigned int pollfirstfree = 1; /* 0 is skipped to simplify logics */ + +static inline void +cleanup_poll(int fd, unsigned int poll_index) +{ + if (!pollfds[poll_index].events) { + pollfh[poll_index]->eventdata = NULL; + cbdataUnreference(pollfh[poll_index]); + pollfds[poll_index].fd = -1; + if (poll_index < pollfirstfree) + pollfirstfree = poll_index; + if (poll_index == pollnfds) { + /* Shrink the active set */ + while(pollnfds > 0 && pollfds[pollnfds].fd == -1) + pollnfds--; + } + } +} + +static inline void +comm_read_event(filehandle *fh, int fd, int poll_index) +{ + int done = fh->read_handler(fh); + + if (done) { + pollfds[poll_index].events &= ~POLLIN; + fh->read_handler = NULL; + cleanup_poll(fd, (unsigned int)poll_index); + } +} + + +static inline void +comm_write_event(filehandle *fh, int fd, int poll_index) +{ + int done = fh->write_handler(fh); + + if (done) { + pollfds[poll_index].events &= ~POLLOUT; + fh->write_handler = NULL; + cleanup_poll(fd, (unsigned int)poll_index); + } +} + +#define CALLBACK_MAGIC 16 +void +ncomm_handle_events(int timeout) +{ + int poll_index; + struct pollfd *pollfd; + int fds = poll(pollfds+1 /* skip position 0 */, pollnfds, timeout); + int callback_limit = CALLBACK_MAGIC; + for (poll_index=1, pollfd = pollfds+1; poll_index <= (int)pollnfds && fds > 0; poll_index++, pollfd++) { + short revents = pollfd->revents; + if(revents) { + int fd = pollfd->fd; + filehandle *fh = pollfh[poll_index]; + assert(fh->fd == fd); + assert(fh->eventdata == &pollfds[poll_index]); + fds--; + if (revents & POLLIN) { + comm_read_event(fh, fd, poll_index); + } else if (revents & POLLOUT) { + comm_write_event(fh, fd, poll_index); + } else if (revents & (POLLHUP | POLLERR | POLLNVAL)) { + short events = pollfds[poll_index].events; + /* I am pretty sure there is better ways to handle errors.. */ + if (events & POLLOUT) + comm_write_event(fh, fd, poll_index); + else if (events & POLLIN) + comm_read_event(fh, fd, poll_index); + } + if (--callback_limit == 0) { + ncomm_call_callbacks(); + callback_limit = CALLBACK_MAGIC; + } + } + } + if (callback_limit != CALLBACK_MAGIC) + ncomm_call_callbacks(); +} + +static void +comm_register_for_event(filehandle *fh, enum comm_event_type event) +{ + struct pollfd *pollfd = fh->eventdata; + int fd = fh->fd; + short events = 0; + switch (event) { + case EVENT_READ: + events = POLLIN; + break; + case EVENT_WRITE: + events = POLLOUT; + break; + default: + /* ERROR! */ + return; + } + if (!pollfd) { + int poll_index = pollfirstfree; + while (pollfds[poll_index].fd >= 0 && poll_index < (int)pollnfds) + poll_index++; + if (poll_index > (int)pollnfds) + pollnfds = (unsigned int)poll_index; + pollfirstfree = poll_index + 1; + pollfd = &pollfds[poll_index]; + pollfd->fd = fd; + pollfh[poll_index] = cbdataReference(fh); + fh->eventdata = pollfd; + } + assert(pollfd->fd == fd); + pollfd->events |= events; +} + +void +comm_register_for_read_event(filehandle *fh, COMMEVENTREAD *handler) +{ + assert(!fh->read_handler); + fh->read_handler = handler; + comm_register_for_event(fh, EVENT_READ); +} + +void +comm_register_for_write_event(filehandle *fh, COMMEVENTWRITE *handler) +{ + assert(!fh->write_handler); + fh->write_handler = handler; + comm_register_for_event(fh, EVENT_WRITE); +} Index: squid/src/ncomm_test.c diff -u /dev/null squid/src/ncomm_test.c:1.1.2.9 --- /dev/null Tue Sep 28 18:37:31 2004 +++ squid/src/ncomm_test.c Tue Mar 6 23:22:24 2001 @@ -0,0 +1,199 @@ +#include "squid.h" + +typedef struct { + filehandle *client; + filehandle *server; +} connection; + +CBDATA_TYPE(connection); + +void fatalf(const char *fmt,...) +{ + fatal(fmt); +} + +void fatal(const char *message) +{ + fprintf(stderr, "FATAL: %s (%s)\n", message, strerror(errno)); + abort(); +} + +static void +got_server_data(filehandle *fh, IOBuf *buf, int offset, int len, int error, void *cbdata) +{ + connection *conn = cbdata; + printf("Got %d server bytes\n", len); + if (len > 0) { + ncomm_write(conn->client, buf, NULL, NULL); + ncomm_read(fh, got_server_data, conn); + } else { + ncomm_close(conn->client); + if (ncomm_closed(fh)) + cbdataFree(conn); + } +} + +static void +got_client_data(filehandle *fh, IOBuf *buf, int offset, int len, int error, void *cbdata) +{ + connection *conn = cbdata; + printf("Got %d client bytes\n", len); + if (len > 0) { + ncomm_write(conn->server, buf, NULL, NULL); + ncomm_read(fh, got_client_data, conn); + } else { + ncomm_close(conn->server); + if (ncomm_closed(fh)) + cbdataFree(conn); + } +} + +static void +new_server_connection(filehandle *fh, int error, struct sockaddr *local, struct sockaddr *remote, int addrsize, void *cbdata) +{ + connection *conn = cbdata; + if (error) { + errno = error; + fatal("server connect failed"); + } + conn->server = cbdataReference(fh); + ncomm_read(conn->client, got_client_data, conn); + ncomm_read(conn->server, got_server_data, conn); +} + +static void +new_client_connection(filehandle *fh, int error, struct sockaddr *local, struct sockaddr *remote_client, int addrsize, void *cbdata) +{ + connection *conn; + struct sockaddr_in remote; + printf("New connection!\n"); + conn = cbdataAlloc(connection); + conn->client = cbdataReference(fh); + memset(&remote, 0, sizeof remote); + remote.sin_family = AF_INET; + remote.sin_port = htons(80); + inet_aton("127.0.0.1", &remote.sin_addr); + ncomm_connect(SOCK_STREAM, 0, NULL, (struct sockaddr *)&remote, sizeof remote, new_server_connection, conn); +} + +static void +new_debug_connection(filehandle *fh, int error, struct sockaddr *local, struct sockaddr *remote_client, int addrsize, void *cbdata) +{ + if (fh) { + IOBuf *buf = memReport(); + ncomm_write(fh, buf, NULL, NULL); + cbdataUnreference(buf); + ncomm_close(fh); + } +} + +static void destroy_connection(void *cbdata) +{ + connection *conn = cbdata; + + cbdataUnreference(conn->server); + cbdataUnreference(conn->client); +} + +int main(int argc, char **argv) +{ + struct sockaddr_in me; + filehandle *lfh, *debugfh; + cbdataInit(); + memInit(); + memBuf_module_init(); + ncomm_module_init(); + + ConfigFile = xstrdup(DefaultConfigFile); + + memInitModule(); + + parseConfigFile(ConfigFile); + + + clientHttpConnectionsOpen(); + + CBDATA_INIT_TYPE_FREECB(connection, destroy_connection); + + memset(&me, 0, sizeof(me)); + me.sin_family = AF_INET; + me.sin_port = htons(45678); + lfh = ncomm_listen(SOCK_STREAM, 0, (struct sockaddr *)&me, sizeof(me), 8192, new_client_connection, NULL); + me.sin_port = htons(55555); + debugfh = ncomm_listen(SOCK_STREAM, 0, (struct sockaddr *)&me, sizeof(me), 8192, new_debug_connection, NULL); + + while(1) + ncomm_handle_events(1000); + + return 0; +} + + + + +/* DUMMY while testing */ + +void peerDestroy(void *data) { } +int authenticateSchemeCount(void) { return 0; } +int authenticateActiveSchemeCount(void) { return 0; } +const ipcache_addrs *ipcache_gethostbyname(const char *host, int flags) { return NULL; } +void ipcache_nbgethostbyname(const char *name, IPH *handler, void *cbdata) { handler(NULL, cbdata); } +ipcache_addrs *ipcacheCheckNumeric(const char *name) { return NULL; } +const char *fqdncache_gethostbyaddr(struct in_addr saddr, int flags) { return NULL; } +void fqdncache_nbgethostbyaddr(struct in_addr saddr, FQDNH *handler, void *cbdata) { handler(NULL, cbdata); } +int clientdbEstablished(struct in_addr saddr, int something) { return 0; } +int asnMatchIp(void *data, struct in_addr saddr) { return 0; } +void enter_suid(void) { } +void leave_suid(void) { } +void cachemgrRegister(const char *a, const char *b, OBJH *c, int d, int e) { } +void storeDirConfigure(void) { } +void storeConfigure(void) { } +const char *uniqueHostname(void) { return "henrik"; } +void storeAppend(StoreEntry *a, const char *b, int c) { } +void storeAppendPrintf(StoreEntry *a, const char *b,...) { } +struct in_addr inaddrFromHostent(const struct hostent *hp) { struct in_addr addr = { s_addr : INADDR_ANY }; return addr; } +int authenticateAuthSchemeId(const char *typestr) { return -1; } +char *neighborTypeStr(const peer * e) { return NULL; } +void dump_peer_options(StoreEntry *a, peer *b) { } +PeerDigest *peerDigestCreate(peer * p) { return NULL; } +void peerClearRR(void *a) { } +peer *peerFindByName(const char *a) { return NULL; } +int internalCheck(const char *urlpath) { return 0; } +char *internalLocalUri(const char *dir, const char *name) { return "http://UNKNOWN/"; }; +int errorReservePageId(const char *page_name) { return 0; } +auth_user_request_t *authenticateGetAuthUser(const char *proxy_auth) { return NULL; } +int authenticateValidateUser(auth_user_request_t *a) { return 0; } +char *authenticateUserRequestUsername(auth_user_request_t *a) { return NULL; } +void authenticateAuthUserRequestLock(auth_user_request_t *a) { } +void authenticateAuthUserRequestSetIp(auth_user_request_t *a, struct in_addr b) { } +int authenticateUserAuthenticated(auth_user_request_t *a) { return 0; } +void authenticateAuthenticateUser(auth_user_request_t *a, request_t *b, ConnStateData *c, http_hdr_type d) { } +int authenticateDirection(auth_user_request_t *a) { return 0; } +void authenticateAuthUserRequestUnlock(auth_user_request_t *a) { } +int authenticateCheckAuthUserIP(struct in_addr request_src_addr, auth_user_request_t * auth_user) { return 0; } +void authenticateStart(auth_user_request_t *a, RH *b, void *c) { } +void identStart(struct sockaddr_in *me, struct sockaddr_in *peer, IDCB * callback, void *cbdata) { } +void requestUnlink(request_t *a) { } +request_t *requestLink(request_t *) + +void +kb_incr(kb_t * k, size_t v) +{ + k->bytes += v; + k->kb += (k->bytes >> 10); + k->bytes &= 0x3FF; +} + +int +stringHasCntl(const char *s) +{ + unsigned char c; + while ((c = (unsigned char) *s++) != '\0') { + if (c <= 0x1f) + return 1; + if (c >= 0x7f && c <= 0x9f) + return 1; + } + return 0; +} + Index: squid/src/peer_digest.c diff -u squid/src/peer_digest.c:1.10 squid/src/peer_digest.c:1.6.8.5 --- squid/src/peer_digest.c:1.10 Wed Oct 24 02:42:13 2001 +++ squid/src/peer_digest.c Sat Nov 17 05:11:58 2001 @@ -327,7 +327,7 @@ /* push towards peer cache */ debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n"); - fwdStart(-1, e, req); + fwdStart(NULL, e, req); cbdataLock(fetch); cbdataLock(fetch->pd); storeClientCopy(fetch->sc, e, 0, 0, 4096, memAllocate(MEM_4K_BUF), Index: squid/src/protos.h diff -u squid/src/protos.h:1.41 squid/src/protos.h:1.18.8.17 --- squid/src/protos.h:1.41 Tue Nov 13 14:19:33 2001 +++ squid/src/protos.h Sat Nov 17 05:11:58 2001 @@ -145,6 +145,7 @@ extern int commSetNonBlocking(int fd); extern int commUnsetNonBlocking(int fd); extern void commSetCloseOnExec(int fd); + extern int comm_accept(int fd, struct sockaddr_in *, struct sockaddr_in *); extern void comm_close(int fd); #if LINGERING_CLOSE @@ -157,7 +158,6 @@ extern int comm_open(int, int, struct in_addr, u_short port, int, const char *note); extern int comm_openex(int, int, struct in_addr, u_short, int, unsigned char TOS, const char *); extern u_short comm_local_port(int fd); - extern void commSetSelect(int, unsigned int, PF *, void *, time_t); extern void comm_add_close_handler(int fd, PF *, void *); extern void comm_remove_close_handler(int fd, PF *, void *); @@ -595,6 +595,8 @@ extern int ipcacheAddEntryFromHosts(const char *name, const char *ipaddr); /* MemBuf */ +extern void memBuf_module_init(void); +extern void memBuf_module_shutdown(void); /* init with specific sizes */ extern void memBufInit(MemBuf * mb, mb_size_t szInit, mb_size_t szMax); /* init with defaults */ @@ -698,7 +700,7 @@ extern peer *netdbClosestParent(request_t *); extern void netdbHostData(const char *host, int *samp, int *rtt, int *hops); -extern void cachemgrStart(int fd, request_t * request, StoreEntry * entry); +extern void cachemgrStart(request_t * request, StoreEntry * entry); extern void cachemgrRegister(const char *, const char *, OBJH *, int, int); extern void cachemgrInit(void); @@ -712,7 +714,7 @@ extern void peerDigestStatsReport(const PeerDigest * pd, StoreEntry * e); /* forward.c */ -extern void fwdStart(int, StoreEntry *, request_t *); +extern void fwdStart(filehandle *fh, StoreEntry *, request_t *); extern DEFER fwdCheckDeferRead; extern void fwdFail(FwdState *, ErrorState *); extern void fwdUnregister(int fd, FwdState *); @@ -789,13 +791,12 @@ extern void start_announce(void *unused); -extern void sslStart(int fd, const char *, request_t *, size_t *, int *); +extern void sslStart(filehandle *client_fh, const char *, request_t *, size_t *, int *); extern void waisStart(FwdState *); /* ident.c */ #if USE_IDENT -extern void identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, - IDCB * callback, void *cbdata); +extern void identStart(struct sockaddr *local, struct sockaddr *remote, IDCB * callback, void *cbdata); extern void identInit(void); #endif @@ -865,10 +866,7 @@ extern int memPoolInUseCount(const MemPool * pool); extern size_t memPoolInUseSize(const MemPool * pool); extern int memPoolUsedCount(const MemPool * pool); -extern void memPoolReport(const MemPool * pool, StoreEntry * e); - -/* Mem */ -extern void memReport(StoreEntry * e); +extern IOBuf *memReport(void); extern int stmemFreeDataUpto(mem_hdr *, int); extern void stmemAppend(mem_hdr *, const char *, int); @@ -1151,6 +1149,7 @@ extern void dlinkDelete(dlink_node * m, dlink_list * list); extern void dlinkNodeDelete(dlink_node * m); extern dlink_node *dlinkNodeNew(void); +extern void *dlinkGetFirst(dlink_list *); extern void kb_incr(kb_t *, size_t); extern double gb_to_double(const gb_t *); @@ -1317,6 +1316,31 @@ */ extern StatCounters *snmpStatGet(int); +/* + * ncomm.c + */ +void ncomm_module_init(void); +void ncomm_module_shutdown(void); +void ncomm_handle_events(int timeout); +void ncomm_close(filehandle *fh); +int ncomm_closed(filehandle *fh); +void ncomm_abort(filehandle *fh); +filehandle * ncomm_listen(int sock_type, int proto, struct sockaddr *where, int addrsize, int backlog, COMMNEWCB *callback, void *cbdata); +filehandle * ncomm_listen_transparent(int sock_type, int proto, struct sockaddr *where, int addrsize, int backlog, COMMNEWCB *callback, void *cbdata); +filehandle * ncomm_accept(int sock_type, int proto, struct sockaddr *where, struct sockaddr *from, int addrsize, COMMNEWCB callback, void *cbdata); +filehandle * ncomm_connect(int sock_type, int proto, const struct sockaddr *local, const struct sockaddr *remote, int addrsize, COMMNEWCB *callback, void *cbdata); +void ncomm_read(filehandle *fh, COMMIOCB *callback, void *cbdata); +void ncomm_read_limited(filehandle *fh, size_t max_size, COMMIOCB *callback, void *cbdata); +void ncomm_write(filehandle *fh, IOBuf *buf, COMMIOCB *callback, void *cbdata); +void ncomm_write_fragment(filehandle *fh, IOBuf *buf, size_t offset, size_t len, COMMIOCB *callback, void *cbdata); +void ncomm_write_mbuf(filehandle *fh, MemBuf mb, COMMIOCB *callback, void *cbdata); +int ncomm_sendto(filehandle *fh, const struct sockaddr *to_addr, int addr_len, const void *msg, int msglen); +int ncomm_add_close_handler(filehandle *fh, COMMCLOSECB *handler, void *cbdata); +IOBuf *IOBufAlloc(size_t size); +IOBuf *IOBufCreate(void *data, size_t size); +IOBuf *IOBufCreateFromMemBuf(MemBuf *mb); +extern void ncomm_note(filehandle *fh, const char *); + /* Vary support functions */ int varyEvaluateMatch(StoreEntry * entry, request_t * req); Index: squid/src/squid.h diff -u squid/src/squid.h:1.13 squid/src/squid.h:1.9.10.7 --- squid/src/squid.h:1.13 Tue Nov 13 14:19:33 2001 +++ squid/src/squid.h Sat Nov 17 05:11:58 2001 @@ -463,6 +463,17 @@ */ #define INDEXSD(i) (&Config.cacheSwap.swapDirs[(i)]) +/* + * macros to simplify cbdata operations + * Usage: + * pointer = cbdataReference(cbdata); + * pointer = cbdataEatReference(cbdata); + * cbdataUnreference(&cbdata); + */ +#define cbdataReference(data) (cbdataLock(data), data) +#define cbdataUnreference(data) data = (cbdataUnlock(data), NULL) +#define cbdataEatReference(data) data; data = NULL + #define FD_READ_METHOD(fd, buf, len) (*fd_table[fd].read_method)(fd, buf, len) #define FD_WRITE_METHOD(fd, buf, len) (*fd_table[fd].write_method)(fd, buf, len) Index: squid/src/ssl.c diff -u squid/src/ssl.c:1.13 squid/src/ssl.c:1.6.12.5 --- squid/src/ssl.c:1.13 Tue Oct 30 05:32:08 2001 +++ squid/src/ssl.c Sat Nov 17 05:11:58 2001 @@ -35,6 +35,7 @@ #include "squid.h" +#if NOT_YET_PORTED typedef struct { char *url; char *host; /* either request->host or proxy host */ @@ -431,7 +432,7 @@ CBDATA_TYPE(SslStateData); void -sslStart(int fd, const char *url, request_t * request, size_t * size_ptr, int *status_ptr) +sslStart(filehandle *fh, const char *url, request_t * request, size_t * size_ptr, int *status_ptr) { /* Create state structure. */ SslStateData *sslState = NULL; @@ -547,7 +548,7 @@ httpHeaderClean(&hdr_out); packerClean(&p); memBufAppend(&mb, "\r\n", 2); - xstrncpy(sslState->client.buf, mb.buf, SQUID_TCP_SO_RCVBUF); + xstrncpy(sslState->client.buf, *mb.bufp, SQUID_TCP_SO_RCVBUF); debug(26, 3) ("sslProxyConnected: Sending {%s}\n", sslState->client.buf); sslState->client.len = mb.size; memBufClean(&mb); @@ -605,3 +606,9 @@ sslConnectDone, sslState); } +#else +void +sslStart(filehandle *fh, const char *url, request_t * request, size_t * size_ptr, int *status_ptr) +{ +} +#endif /* NOT_YET_PORTED */ Index: squid/src/stat.c diff -u squid/src/stat.c:1.13 squid/src/stat.c:1.8.8.4 --- squid/src/stat.c:1.13 Wed Oct 24 02:42:13 2001 +++ squid/src/stat.c Sat Nov 17 05:11:58 2001 @@ -1398,19 +1398,21 @@ clientHttpRequest *http; ConnStateData *conn; StoreEntry *e; - int fd; + filehandle *fh; for (i = ClientActiveRequests.head; i; i = i->next) { http = i->data; assert(http); conn = http->conn; storeAppendPrintf(s, "Connection: %p\n", conn); if (conn) { - fd = conn->fd; - storeAppendPrintf(s, "\tFD %d, read %d, wrote %d\n", fd, + fh = conn->fh; +#if NOT_YET_PORTED + storeAppendPrintf(s, "\tFH %p, read %d, wrote %d\n", fh, fd_table[fd].bytes_read, fd_table[fd].bytes_written); - storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc); - storeAppendPrintf(s, "\tin: buf %p, offset %ld, size %ld\n", - conn->in.buf, (long int) conn->in.offset, (long int) conn->in.size); + storeAppendPrintf(s, "\tFH desc: %s\n", ncomm_get_note(fh)); +#endif + storeAppendPrintf(s, "\tin: buf %p, size %ld\n", + conn->in, (long int)IOBufSize(conn->in)); storeAppendPrintf(s, "\tpeer: %s:%d\n", inet_ntoa(conn->peer.sin_addr), ntohs(conn->peer.sin_port)); Index: squid/src/store.c diff -u squid/src/store.c:1.16 squid/src/store.c:1.9.12.6 --- squid/src/store.c:1.16 Wed Oct 24 02:42:13 2001 +++ squid/src/store.c Sat Nov 17 05:11:58 2001 @@ -121,7 +121,6 @@ #endif mem->log_url = xstrdup(log_url); mem->object_sz = -1; - mem->fd = -1; /* XXX account log_url */ debug(20, 3) ("new_MemObject: returning %p\n", mem); return mem; @@ -159,7 +158,7 @@ * There is no way to abort FD-less clients, so they might * still have mem->clients set if mem->fd == -1 */ - assert(mem->fd == -1 || mem->clients.head == NULL); + assert(mem->clients.head == NULL); httpReplyDestroy(mem->reply); requestUnlink(mem->request); mem->request = NULL; Index: squid/src/store_client.c diff -u squid/src/store_client.c:1.9 squid/src/store_client.c:1.6.12.4 --- squid/src/store_client.c:1.9 Wed Oct 24 02:42:13 2001 +++ squid/src/store_client.c Sat Nov 17 05:11:58 2001 @@ -512,13 +512,6 @@ return 0; if (mem->clients.head == NULL) return 0; - if (sc == mem->clients.head->data) { - /* - * If we are unregistering the _first_ client for this - * entry, then we have to reset the client FD to -1. - */ - mem->fd = -1; - } dlinkDelete(&sc->node, &mem->clients); mem->nclients--; if (e->store_status == STORE_OK && e->swap_status != SWAPOUT_DONE) Index: squid/src/store_dir.c diff -u squid/src/store_dir.c:1.19 squid/src/store_dir.c:1.12.8.5 --- squid/src/store_dir.c:1.19 Wed Oct 24 02:42:14 2001 +++ squid/src/store_dir.c Sat Nov 17 05:11:59 2001 @@ -321,6 +321,8 @@ { SwapDir *SD; int i; + if (Config.cacheSwap.swapDirs == NULL) + fatal("No cache_dir's specified in config file"); Config.Swap.maxSize = 0; for (i = 0; i < Config.cacheSwap.n_configured; i++) { SD = &Config.cacheSwap.swapDirs[i]; Index: squid/src/store_key_md5.c diff -u squid/src/store_key_md5.c:1.6 squid/src/store_key_md5.c:1.5.12.2 --- squid/src/store_key_md5.c:1.6 Fri Apr 13 17:31:02 2001 +++ squid/src/store_key_md5.c Sat Apr 14 06:43:18 2001 @@ -45,7 +45,7 @@ memBufReset(&mb); for (i = 0; i < MD5_DIGEST_CHARS; i++) memBufPrintf(&mb, "%02X", *(key + i)); - return mb.buf; + return *mb.bufp; } const cache_key * Index: squid/src/structs.h diff -u squid/src/structs.h:1.47 squid/src/structs.h:1.24.8.16 --- squid/src/structs.h:1.47 Wed Oct 24 02:42:14 2001 +++ squid/src/structs.h Sat Nov 17 05:11:59 2001 @@ -743,6 +743,9 @@ int weak; /* true if it is a weak validator */ }; +/* + * old comm.c data + */ struct _fde { unsigned int type; u_short local_port; @@ -787,6 +790,8 @@ DEFER *defer_check; /* check if we should defer read */ void *defer_data; CommWriteStateData *rwstate; /* State data for comm_write */ + /* ncomm stuff */ + filehandle *fh; READ_HANDLER *read_method; WRITE_HANDLER *write_method; #if USE_SSL @@ -807,13 +812,12 @@ /* note: when updating this struct, update MemBufNULL #define */ struct _MemBuf { /* public, read-only */ - char *buf; + char **bufp; mb_size_t size; /* used space, does not count 0-terminator */ /* private, stay away; use interface function instead */ mb_size_t max_capacity; /* when grows: assert(new_capacity <= max_capacity) */ mb_size_t capacity; /* allocated space */ - FREE *freefunc; /* what to use to free the buffer, NULL after memBufFreeFunc() is called */ }; /* see Packer.c for description */ @@ -1078,12 +1082,9 @@ }; struct _ConnStateData { - int fd; - struct { - char *buf; - off_t offset; - size_t size; - } in; + filehandle *fh; + MemBuf *in; + off_t in_offset; struct { size_t size_left; /* How much body left to process */ request_t *request; /* Parameters passed to clientReadBody */ @@ -1484,7 +1485,6 @@ struct timeval start_ping; IRCB *ping_reply_callback; void *ircb_data; - int fd; /* FD of client creating this entry */ struct { STABH *callback; void *data; @@ -1943,7 +1943,7 @@ }; struct _FwdState { - int client_fd; + filehandle *client_fh; StoreEntry *entry; request_t *request; FwdServer *servers; Index: squid/src/tools.c diff -u squid/src/tools.c:1.19 squid/src/tools.c:1.10.12.8 --- squid/src/tools.c:1.19 Sat Nov 17 17:15:42 2001 +++ squid/src/tools.c Wed Nov 21 18:19:02 2001 @@ -62,8 +62,6 @@ extern void (*failure_notify) (const char *); -MemPool *dlink_node_pool = NULL; - void releaseServerSockets(void) { @@ -767,64 +765,6 @@ return p ? p : "(NULL)"; } -dlink_node * -dlinkNodeNew() -{ - if (dlink_node_pool == NULL) - dlink_node_pool = memPoolCreate("Dlink list nodes", sizeof(dlink_node)); - /* where should we call memPoolDestroy(dlink_node_pool); */ - return memPoolAlloc(dlink_node_pool); -} - -/* the node needs to be unlinked FIRST */ -void -dlinkNodeDelete(dlink_node * m) -{ - if (m == NULL) - return; - memPoolFree(dlink_node_pool, m); -} - -void -dlinkAdd(void *data, dlink_node * m, dlink_list * list) -{ - m->data = data; - m->prev = NULL; - m->next = list->head; - if (list->head) - list->head->prev = m; - list->head = m; - if (list->tail == NULL) - list->tail = m; -} - -void -dlinkAddTail(void *data, dlink_node * m, dlink_list * list) -{ - m->data = data; - m->next = NULL; - m->prev = list->tail; - if (list->tail) - list->tail->next = m; - list->tail = m; - if (list->head == NULL) - list->head = m; -} - -void -dlinkDelete(dlink_node * m, dlink_list * list) -{ - if (m->next) - m->next->prev = m->prev; - if (m->prev) - m->prev->next = m->next; - if (m == list->head) - list->head = m->next; - if (m == list->tail) - list->tail = m->prev; - m->next = m->prev = NULL; -} - void kb_incr(kb_t * k, size_t v) { @@ -834,43 +774,6 @@ } void -gb_flush(gb_t * g) -{ - g->gb += (g->bytes >> 30); - g->bytes &= (1 << 30) - 1; -} - -double -gb_to_double(const gb_t * g) -{ - return ((double) g->gb) * ((double) (1 << 30)) + ((double) g->bytes); -} - -const char * -gb_to_str(const gb_t * g) -{ - /* - * it is often convenient to call gb_to_str several times for _one_ printf - */ -#define max_cc_calls 5 - typedef char GbBuf[32]; - static GbBuf bufs[max_cc_calls]; - static int call_id = 0; - double value = gb_to_double(g); - char *buf = bufs[call_id++]; - if (call_id >= max_cc_calls) - call_id = 0; - /* select format */ - if (value < 1e9) - snprintf(buf, sizeof(GbBuf), "%.2f MB", value / 1e6); - else if (value < 1e12) - snprintf(buf, sizeof(GbBuf), "%.2f GB", value / 1e9); - else - snprintf(buf, sizeof(GbBuf), "%.2f TB", value / 1e12); - return buf; -} - -void debugObj(int section, int level, const char *label, void *obj, ObjPackMethod pm) { MemBuf mb; @@ -879,7 +782,7 @@ memBufDefInit(&mb); packerToMemInit(&p, &mb); (*pm) (obj, &p); - debug(section, level) ("%s%s", label, mb.buf); + debug(section, level) ("%s%s", label, *mb.bufp); packerClean(&p); memBufClean(&mb); } Index: squid/src/typedefs.h diff -u squid/src/typedefs.h:1.25 squid/src/typedefs.h:1.15.8.11 --- squid/src/typedefs.h:1.25 Wed Oct 10 11:07:43 2001 +++ squid/src/typedefs.h Sat Nov 17 05:11:59 2001 @@ -92,6 +92,7 @@ typedef struct _dnsserver_t dnsserver_t; typedef struct _dwrite_q dwrite_q; typedef struct _ETag ETag; +typedef struct _file_handle filehandle; typedef struct _fde fde; typedef struct _fileMap fileMap; typedef struct _HttpReply http_reply; @@ -360,4 +361,12 @@ typedef int STDIRSELECT(const StoreEntry *); +/* + * ncomm.c + */ +typedef MemBuf IOBuf; +typedef void COMMNEWCB(filehandle *fh, int error, struct sockaddr *local, struct sockaddr *peer, int addrsize, void *cbdata); +typedef void COMMIOCB(filehandle *fh, IOBuf *buf, int offset, int size, int error, void *cbdata); +typedef void COMMCLOSECB(filehandle *fh, void *cbdata); + #endif /* SQUID_TYPEDEFS_H */ Index: squid/src/urn.c diff -u squid/src/urn.c:1.11 squid/src/urn.c:1.8.8.4 --- squid/src/urn.c:1.11 Wed Oct 24 02:42:14 2001 +++ squid/src/urn.c Sat Nov 17 05:11:59 2001 @@ -139,7 +139,7 @@ if ((urlres_e = storeGetPublic(urlres, METHOD_GET)) == NULL) { urlres_e = storeCreateEntry(urlres, urlres, null_request_flags, METHOD_GET); urnState->sc = storeClientListAdd(urlres_e, urnState); - fwdStart(-1, urlres_e, urlres_r); + fwdStart(NULL, urlres_e, urlres_r); } else { storeLockObject(urlres_e); urnState->sc = storeClientListAdd(urlres_e, urnState); Index: squid/src/wais.c diff -u squid/src/wais.c:1.8 squid/src/wais.c:1.5.12.3 --- squid/src/wais.c:1.8 Wed Oct 24 02:42:14 2001 +++ squid/src/wais.c Sat Nov 17 05:11:59 2001 @@ -209,7 +209,7 @@ packerClean(&p); } memBufPrintf(&mb, "\r\n"); - debug(24, 6) ("waisSendRequest: buf: %s\n", mb.buf); + debug(24, 6) ("waisSendRequest: buf: %s\n", *mb.bufp); comm_write_mbuf(fd, mb, waisSendComplete, waisState); if (EBIT_TEST(waisState->entry->flags, ENTRY_CACHABLE)) storeSetPublicKey(waisState->entry); /* Make it public */ Index: squid/src/wordlist.c diff -u /dev/null squid/src/wordlist.c:1.1.2.1 --- /dev/null Tue Sep 28 18:37:32 2004 +++ squid/src/wordlist.c Sat Feb 24 15:48:43 2001 @@ -0,0 +1,66 @@ +#include "squid.h" + +void +wordlistDestroy(wordlist ** list) +{ + wordlist *w = NULL; + while ((w = *list) != NULL) { + *list = w->next; + safe_free(w->key); + memFree(w, MEM_WORDLIST); + } + *list = NULL; +} + +const char * +wordlistAdd(wordlist ** list, const char *key) +{ + while (*list) + list = &(*list)->next; + *list = memAllocate(MEM_WORDLIST); + (*list)->key = xstrdup(key); + (*list)->next = NULL; + return (*list)->key; +} + +void +wordlistJoin(wordlist ** list, wordlist ** wl) +{ + while (*list) + list = &(*list)->next; + *list = *wl; + *wl = NULL; +} + +void +wordlistAddWl(wordlist ** list, wordlist * wl) +{ + while (*list) + list = &(*list)->next; + for (; wl; wl = wl->next, list = &(*list)->next) { + *list = memAllocate(MEM_WORDLIST); + (*list)->key = xstrdup(wl->key); + (*list)->next = NULL; + } +} + +void +wordlistCat(const wordlist * w, MemBuf * mb) +{ + while (NULL != w) { + memBufPrintf(mb, "%s\n", w->key); + w = w->next; + } +} + +wordlist * +wordlistDup(const wordlist * w) +{ + wordlist *D = NULL; + while (NULL != w) { + wordlistAdd(&D, w->key); + w = w->next; + } + return D; +} +