Henrik Nordstrom <henrik.nordstrom@ida.his.se>
Daniel O'Callaghan <danny@miriworld.its.unimelb.EDU.AU>
+ George Michaelson <ggm@connect.com.au>
+ Taavi Talvik <taavi@uninet.ee>
+ Luke Howard <lukeh@vurt.schnet.edu.au>
+ Assar Westerlund <assar@pdc.kth.se>
+ James R Grinter <jrg@demon.net>
+ Shigechika Aikawa <shige@luck.imasy.or.jp>
+ Russell Vincent <vincent@ucthpx.uct.ac.za>
Edward Moy <moy@parc.xerox.com>
Jean-Francois Micouleau <Jean-Francois.Micouleau@utc.fr>
+ Ansgar Hockmann <Ansgar.Hockmann@hrz.uni-dortmund.de>
+ Joe Ramey <ramey@jello.csc.ti.com>
+ Kolics Bertold <bertold@tohotom.vein.hu>
+ Doug Urner <dlu@wobble.albatross.com>
+ Markus Gyger <mgyger@itr.ch>
+ Richard Huveneers <Richard.Huveneers@hekkihek.hacom.nl>
+ Markus Stumpf <maex@Space.NET>
Wojtek Sylwestrzak <W.Sylwestrzak@icm.edu.pl>
+ Brian Denehy <B-Denehy@adfa.oz.au>
+ David Luyer <luyer@ucs.uwa.edu.au>
+ Carson Gaspar (carson@lehman.com, carson@cs.columbia.edu)
+ Pete Bentley <pete@demon.net>
+ Alexander B. Demenshin <aldem@barnet.kharkov.ua>
+ Tony Lorimer <tlorimer@au.mdis.com>
Development of this caching software is funded by the National Science
-Foundation. Paid staff members on the caching project are:
+Foundation (grant NCR-9521745). Paid staff members on the caching
+project are:
Duane Wessels <wessels@nlanr.net>
K Claffy <kc@nlanr.net>
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
-
Changes to squid-1.1.alpha2:
- Added Support for RFC931/ident
-==============================================================================
+Changes to squid-1.0.1 (July 8, 1996):
+
+ - Fixed ftpget server looping on socket EOF condition.
+ - Fixed SA_RESETHAND undefined bug.
+ - Fixed half-hour timezone offset bug.
+ - Fixed parse_rfc850() to return -1 instead of 0 upon error.
+ - Added patch for Motorola systems from Tony Lorimer.
+ - Added support for HTTP PUT method.
+ - Added check for <netinet/tcp.h> for HP-UX.
+ - Added GNU General Public License.
+ - Changed ttlSet() to use Date field if Last-Modified is absent.
+ - Changed http.c to not save objects from neighbors which do
+ not have Date, Last-Modified, or Expires values.
+ - Changed some large local character arrays to static.
+
+Changes to squid-1.0.0 (July 1, 1996):
+
+ - Fixed beta17 "fd_lifetime" typo bug
+ - Added 'firewall_ip_list' to configuration options
+ - Set resolver options to disable searching default domains
+ and parent domains.
+ - Added blocking-rebuild -F option.
+ - Fixed storeMaintainSwapSpace to be called every 10 seconds.
+ - Fixed ICP_HIT_OBJ bug causing objects to get stuck in VM.
+ - Fixed matching the ends of domain names (e.g. bar.com no
+ longer matches foobar.com).
+ - Fixed checking return code from fprintf() while writing the
+ clean swap log.
+ - Fixed fatal_dump from storeSwapoutHandle running out of disk
+ space.
+ - Added disabling of a neighbor cache if 95% of replies are
+ UDP_DENIED.
+ - Added accounting for misc memory/data structures
+ - Added 'no-query' option for 'cache_host' config line
+ - Added error reporting to SSL requests.
+ - Fixed SSL bug, client abort was not closing the server
+ side connection.
+ - Fixed checking hierarchy_stoplist bug.
+ - Fixed ipcache error messages by giving each entry its
+ own string.
+ - Use sigaction() instead of signal() if available.
+ - Fixed ipcache bug causing some lookups to get stuck in
+ PENDING state if all dnsservers are busy.
+ - Fixed domain name matching bug when using '.com' instead of
+ 'com'.
+ - Fixed close_handler coredump bug in comm.c.
+ - Removed unnecessary DNS lookup of hostnames in WAIS URLs.
+
+Changes to squid-1.0.beta17 (June 12, 1996):
+
+ - Fixed another ipcache coredump problem where an entry could
+ be released between writing to and reading from dnsserver.
+ - Fixed store.c bug of purging aborted objects.
+ - Cleaned up checkLifetimes() function to make it simpler.
+ - Added visible_hostname support to ftpget.
+ - Fixed null edge dereferencing bug for UDP_HIT_OBJ.
+
+Changes to squid-1.0.beta16 (June 10, 1996):
+
+ - Fixed two coredump-causing bugs in ipcache_unregister().
+ - Changed 'close_handler' to a linked list.
+ - Changed freeing of protodispatch_data structures to use
+ new close_handler (attached to client FD).
+ - Fixed URL handling to accomodate browswers which do not handle
+ relative URL parsing.
+
+Changes to squid-1.0.beta15 (June 9, 1996):
+
+ - Fixed storeSwapoutHandle coredump bug
+ - Fixed DNS lookup failure of neighbor hosts after a few hours
+ of operation
+ - Changed memcpy() to memmove() for overlapping memory copies
+ - Changed store rebuidling to unlink the log-last-clean file
+ in case of a crash during rebuild
+ - Added forwarding loop detection
+ - Changed all memcpy to use xmemcpy which is memmove, bcopy, or
+ memcpy.
+ - Fixed coredump bug from partial dnsserver reads, manifest on
+ FreeBSD and NetBSD.
+
+Changes to squid-1.0.beta14 (June 7, 1996):
+
+ - Fixed coredump bug in icp.c when generating ``Not Modified''
+ replies.
+ - Fixed SSL bug which assumed the requested host name would
+ already be in the IP cache.
+ - Fixed names of generated HTTP reply headers.
+
+Changes to squid-1.0.beta13 (June 7, 1996):
+
+ - Fixed coredump bug where StoreEntry key was free'd too soon.
+ - Fixed UDP_HIT_OBJ bug: cancel the hierarchy timeout and set
+ the ping_status to DONE for UDP_HIT_OBJ replies.
+
+Changes to squid-1.0.beta12 (June 6, 1996):
+
+ - Fixed problem when using udp_outgoing_addr where no ICP
+ packets would be recieved because they were getting sent
+ to the "outgoing" instead of the "incoming" socket.
+ - Fixed objects hanging around in cache after a keychange.
+ - Added ability to restrict neighbor caches with ACLs.
+ ('cache_host_acl').
+ - Fixed ssl FD mismatch bug.
+ - Fixed INADDR_NONE bug on 64bit systems.
+ - Fixed store rebuilding bug; temporary log file was not being
+ truncated.
+ - Made all external processes communicate with TCP sockets
+ (no more Unix domain sockets).
+ - Semi-major rewrite of ipcache implementation.
+ - Fixed a couple memory bugs found by purify.
+ - Fixed sending large (>8192 bytes) HTTP requests.
+ - Added "lazy" server IP address ACL checks (type 'dst').
+ - Changed handling of IMS requests. Now will return "304
+ Not Modified" if the requested object is in the cache
+ and not expired.
+
+Changes to squid-1.0.beta11 (June 1, 1996):
+
+ - Fixed serious memory leak of MemObject->reply structures.
+
+
+Changes to squid-1.0.beta10 (May 31, 1996):
+
+ - Fixed bug when request arrives in fragmented IP packets.
+ - Fixed ACL bug which denied cache manager access while in
+ httpd_accel mode.
+ - Changed ftpget to "fail nicely" for sites which do not allow
+ PORT requests (if compiled with PASVONLY).
+ - Fixed Unix domain socket off-by-one bug in ftpget.
+ - Fixed lingering sockets after shutdown by SIGTERM.
+ - Added dnsserver use histogram to ipcache stats.
+ - Changed domain ACL's to match only the end of the hostname, not
+ just anywhere in the string.
+ - Fixed setuid bugs when pid_filename was not defined
+ - Fixed zero-sized object getting stuck in VM.
+ - Configure checks for working UNIX domain stream sockets
+ - Rotate cache.log before the others
+ - SIGUSR2 now toggles between full and normal debugging
+ - Close and restart ftpget server during logfile rotation
+ - Added memory pools for request_t and MemObject data structures.
+ - Added new address binding options for more control
+
+Changes to squid-1.0.beta9 (May 23, 1996):
+
+ - Fixed storeToString() coredump bug on 'swap_buf'
+ - Added back the CIDR notation functionality to decoding IP
+ address ACLs.
+ - Fixed ftpget listing parsing coredump bug.
+ - Fixed neighborsUdpAck() coredump for late-arriving ICP replies.
+
+Changes to squid-1.0.beta8 (May 22, 1996):
+
+ - More friendly CFLAGS and LDFLAGS for configure
+ - ACL_ALLWEEK bugfix
+ - Added missing increment of UDP connection counter.
+ - Changed ftpget select to check for EWOULDBLOCK/EAGAIN
+ (workaround for broken Solaris select(2)).
+ - Fixed MALLINFO calls for Linux
+ - Fixed strerror() problems on SunOS 4.1.x
+ - Fixed DefaultAnnounceRate; set to zero by defult.
+ - Changed all port variables to u_short.
+ - Created AF_UNIX versions of comm_open(), comm_connect().
+ - Changed ftpget server to use UNIX domain socket.
+ - Removed RESET_SIGNAL_HANDLER check--always reset the signal
+ handler.
+ - Added instrumentation of basic IPCache stats.
+ - Fixed calculation of neighbor average RTT.
+ - Added 'outbound_addr_list' to config
+ - Change getFirstParent() to getFirstUpParent().
+ - Changed ftpget to use an additional pipe() for crash detection
+ - Added ICP_OP_DENIED message type
+ - Added patches for Nextstep port from Luke Howard
+ <lukeh@vurt.schnet.edu.au>
+ - Added a lifetime to HTTP server connections being deferred.
+ - Added IP address ranges in 'src' ACLs
+ - Added FQDN's in 'src' ACLs
+ - Fixed request structure free-memory-read/coredump bug.
+ - Changed icp.c to select on client socket to detect aborts.
+ - Better compliance with HTTP/1.1 *DRAFT* regarding which reply
+ codes can be cached.
+ - Added 'hierarchy_stoplist' configuration option.
+ - Changed mallopt option M_MXFAST to 512 bytes.
+ - Added -Y option to only return UDP_HIT or UDP_DENIED during
+ store reload.
+ - Added UDP_HIT_OBJ type. Just like a UDP_HIT, but object data
+ is returned in the UDP packet if it will fit; saves a TCP
+ connection. Not compiled in by default, add -DUDP_HIT_WITH_OBJ
+ to src/Makefile DEFINES.
+
+Changes to squid-1.0.beta7:
+
+ - Fixed comm_udp_sendto continuous loop bug
+ - Fixed URLs-with-colon-but-no-port-number bug
+ - Fixed sending ICP queries for HEAD requests
+ - Changed 'server_list' output. Added RTT, Fetches, Hits, Misses,
+ and percents.
+ - Fixed setuid bug causing some logs to be owned by root.
+ - Fixed virtual host mode (-V option)
+ - Added read(2) instrumentation for HTTP and FTP.
+ - Changed neighbor initialization to continue if DNS lookup fails.
+ - Lint cleanup
+
+Changes to squid-1.0.beta6:
+
+ - Fixed null error message coredump in ftpget.
+ - Added -m Method option to `client'.
+ - Fixed ftpget server bug with missing trailing slash.
+ - Removed 'connect_ports' from config, use general ACLs instead.
+ - Changed requested listen queue length to 1/4 of getMaxFD().
+ - Rewrote SSL/CONNECT handlers. Now doesn't use a StoreEntry.
+ - Fixed some aborted objects getting stuck in VM bug.
+ - Fixed ftpget PASV reply sscanf to work for VMS ftpd.
+ - Changed FTP URL parsing to use urlParse().
+ - Changed ftpget to skip RETR command if URLs ends with '/'.
+ - Changed ftpget to display README at the bottom if there are other
+ server messages.
+ - Changed ftpget to not reopen a new data connection
+ if one is already open.
+ - Fixed handling of FTP URLs with spaces (and other unsafe characters)
+ - Changed ftpget to only generate BASE HREF if the FTP URL does
+ not end with '/'.
+
+Changes to squid-1.0.beta5:
+
+ - Fixed cachemgr to send 'HTTP/1.0' on request so it works
+ with beta4 fixes to icp.c.
+
+Changes to squid-1.0.beta4:
+
+ - Added a handler to restart the ftpget server.
+ - Fixed access checks for ICP by parsing the requested URL.
+ - Added "magic marker" to ftpget-generated errors so they can
+ be negative-cached.
+ - Added a small run-time check to configure to see if signal
+ handlers should be restarted after invocation (ala SYSV).
+ - Determine Maximum filedescriptors in configure and change
+ FD_SETSIZE if needed.
+ - Changed read stall algorithm for HTTP. No don't wait until
+ the object is in DELETE_BEHIND mode to stall the server read
+ and wait for the client to catch up. Also changed from 4k to
+ 16k read buffer.
+ - Fixed HTTP request parsing to check for blank line at the
+ end of all requests. Symptoms were "connection reset"
+ messages.
+
+Changes to squid-1.0.beta3:
+
+ - Added ftpget '-C minport:maxport' option
+ - Fixed PROTO_MAX fencepost bug in stat_init().
+ - Fixed Fixed CheckQuickAbort() coredump.
+ - Fixed disabling store.log and hierarchy.log when set to "none"
+ - Fixed numerous problems related to setuid().
+ - Fixed 'check_cache.pl' to use new swaplog format (without "FILE").
+ - Fixed ACL coredumps when checking NULL words.
+ - Changed pid_filename to be written and unlinked as root.
+ - Added "-i seconds" option to 'client' for testing IMS GET.
+ - Fixed a bug where an IMS request caused the valid object to
+ get ejected from the cache.
+ - Fixed continual DEAD_PARENT/REVIVE bug
+ - Fixed ERR_INVALID_URL bug for URLs with a password field.
+ - Added to Release-Notes info about converting 'cache/log' and
+ difference between stoplists and ttl_pattern.
+
+Changes to squid-1.0.beta2:
+
+ - Fixed /bin/csh "$#argv" leftover in RunCache.
+ - Fixed ACL day-of-week bitmask bug.
+ - Fixed missing checks for WAIS in some places.
+ - Fixed chdir(swappath(0)) bug; do chdir() after storeInit().
+ - Changed enumerated structure members to be defined outside
+ of the structure itself (for AIX).
+ - Changed ftpget to fork before reading the request and make
+ sure the entire request is read.
Changes to squid-1.0.beta1 (Apr 19, 1996) from Harvest cached-1.4.pl3:
- Removed all code and references to binary port.
- Removed dual logging to stderr/cache.log.
- Removed old IP access controls ('proxy_allow', etc.)
-
-Changes to 1.0.beta2:
-
- - Fixed /bin/csh "$#argv" leftover in RunCache.
- - Fixed ACL day-of-week bitmask bug.
- - Fixed missing checks for WAIS in some places.
- - Fixed chdir(swappath(0)) bug; do chdir() after storeInit().
- - Changed enumerated structure members to be defined outside
- of the structure itself (for AIX).
- - Changed ftpget to fork before reading the request and make
- sure the entire request is read.
-
-Changes to 1.0.beta3:
-
- - Added ftpget '-C minport:maxport' option
- - Fixed PROTO_MAX fencepost bug in stat_init().
- - Fixed Fixed CheckQuickAbort() coredump.
- - Fixed disabling store.log and hierarchy.log when set to "none"
- - Fixed numerous problems related to setuid().
- - Fixed 'check_cache.pl' to use new swaplog format (without "FILE").
- - Fixed ACL coredumps when checking NULL words.
- - Changed pid_filename to be written and unlinked as root.
- - Added "-i seconds" option to 'client' for testing IMS GET.
- - Fixed a bug where an IMS request caused the valid object to
- get ejected from the cache.
- - Fixed continual DEAD_PARENT/REVIVE bug
- - Fixed ERR_INVALID_URL bug for URLs with a password field.
- - Added to Release-Notes info about converting 'cache/log' and
- difference between stoplists and ttl_pattern.
-
-Changes to squid-1.0.beta4:
-
- - Added a handler to restart the ftpget server.
- - Fixed access checks for ICP by parsing the requested URL.
- - Added "magic marker" to ftpget-generated errors so they can
- be negative-cached.
- - Added a small run-time check to configure to see if signal
- handlers should be restarted after invocation (ala SYSV).
- - Determine Maximum filedescriptors in configure and change
- FD_SETSIZE if needed.
- - Changed read stall algorithm for HTTP. No don't wait until
- the object is in DELETE_BEHIND mode to stall the server read
- and wait for the client to catch up. Also changed from 4k to
- 16k read buffer.
- - Fixed HTTP request parsing to check for blank line at the
- end of all requests. Symptoms were "connection reset"
- messages.
-
-Changes to squid-1.0.beta5:
-
- - Fixed cachemgr to send 'HTTP/1.0' on request so it works
- with beta4 fixes to icp.c.
-
-Changes to squid-1.0.beta6:
-
- - Fixed null error message coredump in ftpget.
- - Added -m Method option to `client'.
- - Fixed ftpget server bug with missing trailing slash.
- - Removed 'connect_ports' from config, use general ACLs instead.
- - Changed requested listen queue length to 1/4 of getMaxFD().
- - Rewrote SSL/CONNECT handlers. Now doesn't use a StoreEntry.
- - Fixed some aborted objects getting stuck in VM bug.
- - Fixed ftpget PASV reply sscanf to work for VMS ftpd.
- - Changed FTP URL parsing to use urlParse().
- - Changed ftpget to skip RETR command if URLs ends with '/'.
- - Changed ftpget to display README at the bottom if there are other
- server messages.
- - Changed ftpget to not reopen a new data connection
- if one is already open.
- - Fixed handling of FTP URLs with spaces (and other unsafe characters)
- - Changed ftpget to only generate BASE HREF if the FTP URL does
- not end with '/'.
-To build and install the Harvest Cache, type:
+To build and install the Squid Cache, type:
% ./configure --prefix=/usr/local/squid
% make all
-This is the Squid Internet Object Cache developed by the National
-Laboratory for Applied Networking Research (NLANR) and Internet
-volunteers. This software is freely available for anyone to use.
-The Squid home page is http://www.nlanr.net/Squid/.
-
-This software is based on the Harvest Object Cache developed by
-the University of Colorado and the University of Southern California.
-The Harvest home page is http://harvest.cs.colorado.edu/.
+SQUID Internet Object Cache http://www.nlanr.net/Squid/
+--------------------------------------------------------
+
+ Squid is the result of efforts by numerous individuals from the
+ Internet community. Development is led by Duane Wessels of the
+ National Laboratory for Applied Network Research and funded by
+ the National Science Foundation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Squid is derived from the ``cached'' software from the ARPA-funded
+Harvest research project. The Harvest home page is
+http://harvest.cs.colorado.edu/.
+
+Please use our mailing lists for questions, feedback and bug fixes
+
+ squid-users@nlanr.net # general questions, pubilc forum
+ squid-bugs@nlanr.net # bugs and fixes
+ squid@nlanr.net # other feedback
-# From configure.in Revision: 1.19
+# From configure.in Revision: 1.18.2.31
ac_aux_dir=
for ac_dir in aux $srcdir/aux; do
if test -f $ac_dir/install-sh; then
echo "$ac_t""$host" 1>&6
-XTRA_CFLAGS=''
CRYPT_LIB=''
if test "$libexecdir" = '${exec_prefix}/libexec'; then
+cat >> confdefs.h <<EOF
+#define CONFIG_HOST_TYPE "$host"
+EOF
+
+
+if test -z "$LDFLAGS"; then
+ LDFLAGS="-g"
+fi
+
+PREST_CFLAGS="$CFLAGS"
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
sleep 5
fi
+if test -z "$PRESET_CFLAGS"; then
+ if test "$GCC" = "yes"; then
+ case "$host" in
+ *-sun-sunos*|*m88k*)
+ # sunos has too many warnings for this to be useful
+ # motorola too
+ ;;
+ *)
+ CFLAGS="$CFLAGS -Wall"
+ ;;
+ esac
+ fi
+
+ case "$host" in
+ *-sgi-irix*)
+ echo "Adding ANSI compile flags for IRIX..."
+ if test "$GCC" = "yes"; then
+ CFLAGS="$CFLAGS -ansi"
+ else
+ CFLAGS="$CFLAGS -D__STRICT_ANSI__"
+ fi
+ ;;
+ *-hp-hpux*)
+ echo "Disabling 'ranlib' for HP-UX..."
+ RANLIB=":"
+ ;;
+ esac
+fi
+
+if test -z "$PRESET_LDFLAGS"; then
+ if test "$GCC" = "yes"; then
+ case "$host" in
+ *)
+ # nothing
+ ;;
+ esac
+ fi
+fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
# On Suns, sometimes $CPP names a directory.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 698 "configure"
+#line 745 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 712 "configure"
+#line 759 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1010 "configure"
+#line 1057 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
ac_save_LIBS="$LIBS"
LIBS="-ldir $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1050 "configure"
+#line 1097 "configure"
#include "confdefs.h"
int main() { return 0; }
ac_save_LIBS="$LIBS"
LIBS="-lx $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1085 "configure"
+#line 1132 "configure"
#include "confdefs.h"
int main() { return 0; }
ac_cv_c_cross=yes
else
cat > conftest.$ac_ext <<EOF
-#line 1122 "configure"
+#line 1169 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1144 "configure"
+#line 1191 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1166 "configure"
+#line 1213 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1184 "configure"
+#line 1231 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
:
else
cat > conftest.$ac_ext <<EOF
-#line 1205 "configure"
+#line 1252 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
for ac_hdr in \
alloca.h \
arpa/inet.h \
+ arpa/nameser.h \
bstring.h \
config.h \
crypt.h \
+ ctype.h \
+ errno.h \
fcntl.h \
+ grp.h \
+ libc.h \
+ malloc.h \
memory.h \
+ netdb.h \
netinet/in.h \
+ netinet/tcp.h \
+ pwd.h \
+ regex.h \
+ resolv.h \
+ signal.h \
+ stdarg.h \
+ stddef.h \
+ stdio.h \
stdlib.h \
string.h \
strings.h \
sys/file.h \
+ sys/param.h \
+ sys/resource.h \
sys/select.h\
+ sys/socket.h \
+ sys/stat.h \
+ sys/syscall.h \
sys/time.h \
sys/types.h \
- sys/syscall.h \
- unistd.h \
- regex.h \
+ sys/un.h \
+ sys/wait.h \
syslog.h \
+ time.h \
+ unistd.h \
+ varargs.h \
do
ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1265 "configure"
+#line 1334 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
echo $ac_n "checking for tm->tm_gmtoff""... $ac_c" 1>&6
cat > conftest.$ac_ext <<EOF
-#line 1296 "configure"
+#line 1365 "configure"
#include "confdefs.h"
#include <time.h>
#include <sys/time.h>
echo $ac_n "checking for extended mallinfo""... $ac_c" 1>&6
cat > conftest.$ac_ext <<EOF
-#line 1322 "configure"
+#line 1391 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <malloc.h>
rm -f conftest*
-echo $ac_n "checking if signal handlers need to be reset""... $ac_c" 1>&6
-if test "$cross_compiling" = yes; then
- cat >> confdefs.h <<\EOF
-#define RESET_SIGNAL_HANDLER 1
-EOF
-
-echo "$ac_t""yes" 1>&6
-else
-cat > conftest.$ac_ext <<EOF
-#line 1355 "configure"
-#include "confdefs.h"
-void handle(s) int s; { return; }
-main(){signal(15,handle);kill(getpid(),15);kill(getpid(),15);exit(0);}
-EOF
-eval $ac_link
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
- echo "$ac_t""no" 1>&6
-else
- cat >> confdefs.h <<\EOF
-#define RESET_SIGNAL_HANDLER 1
-EOF
-
-echo "$ac_t""yes" 1>&6
-fi
-fi
-rm -fr conftest*
-
echo $ac_n "checking size of int""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 1381 "configure"
+#line 1423 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 1415 "configure"
+#line 1457 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1449 "configure"
+#line 1491 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() { return 0; }
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1481 "configure"
+#line 1523 "configure"
#include "confdefs.h"
#ifdef __GNUC__
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1540 "configure"
+#line 1582 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1569 "configure"
+#line 1611 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
-#line 1623 "configure"
+#line 1665 "configure"
#include "confdefs.h"
find_stack_direction ()
{
fi
-echo $ac_n "checking for -lsocket""... $ac_c" 1>&6
-ac_lib_var=`echo socket | tr '.-/+' '___p'`
+echo $ac_n "checking for -lnsl""... $ac_c" 1>&6
+ac_lib_var=`echo nsl | tr '.-/+' '___p'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
-LIBS="-lsocket $LIBS"
+LIBS="-lnsl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1668 "configure"
+#line 1710 "configure"
#include "confdefs.h"
int main() { return 0; }
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo socket | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ ac_tr_lib=HAVE_LIB`echo nsl | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
cat >> confdefs.h <<EOF
#define $ac_tr_lib 1
EOF
- LIBS="-lsocket $LIBS"
+ LIBS="-lnsl $LIBS"
else
echo "$ac_t""no" 1>&6
fi
-echo $ac_n "checking for -lmalloc""... $ac_c" 1>&6
-ac_lib_var=`echo malloc | tr '.-/+' '___p'`
+echo $ac_n "checking for -lsocket""... $ac_c" 1>&6
+ac_lib_var=`echo socket | tr '.-/+' '___p'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
-LIBS="-lmalloc $LIBS"
+LIBS="-lsocket $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1708 "configure"
+#line 1750 "configure"
#include "confdefs.h"
int main() { return 0; }
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- HAVE_LIBMALLOC="yes"; LIBS="$LIBS -lmalloc"
+ ac_tr_lib=HAVE_LIB`echo socket | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lsocket $LIBS"
+
else
echo "$ac_t""no" 1>&6
fi
-echo $ac_n "checking for -lnsl""... $ac_c" 1>&6
-ac_lib_var=`echo nsl | tr '.-/+' '___p'`
+echo $ac_n "checking for -lmalloc""... $ac_c" 1>&6
+ac_lib_var=`echo malloc | tr '.-/+' '___p'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
-LIBS="-lnsl $LIBS"
+LIBS="-lmalloc $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1742 "configure"
+#line 1790 "configure"
#include "confdefs.h"
int main() { return 0; }
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo nsl | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-lnsl $LIBS"
-
+ HAVE_LIBMALLOC="yes"; LIBS="$LIBS -lmalloc"
else
echo "$ac_t""no" 1>&6
fi
ac_save_LIBS="$LIBS"
LIBS="-lresolv $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1782 "configure"
+#line 1824 "configure"
#include "confdefs.h"
int main() { return 0; }
ac_save_LIBS="$LIBS"
LIBS="-lbsd $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1822 "configure"
+#line 1864 "configure"
#include "confdefs.h"
int main() { return 0; }
ac_save_LIBS="$LIBS"
LIBS="-l44bsd $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1863 "configure"
+#line 1905 "configure"
#include "confdefs.h"
int main() { return 0; }
ac_save_LIBS="$LIBS"
LIBS="-lresolv $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1897 "configure"
+#line 1939 "configure"
#include "confdefs.h"
int main() { return 0; }
ac_save_LIBS="$LIBS"
LIBS="-lcrypt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1932 "configure"
+#line 1974 "configure"
#include "confdefs.h"
int main() { return 0; }
echo "Removing -lnsl for IRIX..."
LIBS=`echo $LIBS | sed -e s/-lnsl//`
;;
+ *m88k*)
+ CFLAGS="$CFLAGS -D_SQUID_MOTOROLA_"
+ ;;
+
esac
for ac_func in \
+ bcopy \
getdtablesize \
+ getrusage \
+ lrand48 \
mallinfo \
mallopt \
+ memmove \
regcomp \
regexec \
regfree \
+ res_init \
seteuid \
+ setpgrp \
setresuid \
setrlimit \
+ setsid \
+ sigaction \
+ socketpair \
+ srand48 \
strdup \
- strerror \
sysconf \
syslog \
+ tempnam \
timegm \
do
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1996 "configure"
+#line 2052 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
SQUID_FD_SETSIZE=256
else
cat > conftest.$ac_ext <<EOF
-#line 2046 "configure"
+#line 2102 "configure"
#include "confdefs.h"
#include <unistd.h>
+#include <sys/time.h> /* needed on FreeBSD */
#include <sys/param.h>
#include <sys/resource.h>
main() {
EOF
+echo $ac_n "checking Default UDP send buffer size""... $ac_c" 1>&6
+if test "$cross_compiling" = yes; then
+ SQUID_UDP_SO_SNDBUF=8192
+else
+cat > conftest.$ac_ext <<EOF
+#line 2170 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+main ()
+{
+ int fd,val=0,len=sizeof(int);
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(1);
+ if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) exit(1);
+ if (val<=0) exit(1);
+ fprintf (fopen("conftestval", "w"), "%d\n", val);
+ exit(0);
+}
+
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ SQUID_UDP_SO_SNDBUF=`cat conftestval`
+else
+ SQUID_UDP_SO_SNDBUF=8192
+fi
+fi
+rm -fr conftest*
+echo "$ac_t""$SQUID_UDP_SO_SNDBUF" 1>&6
+cat >> confdefs.h <<EOF
+#define SQUID_UDP_SO_SNDBUF $SQUID_UDP_SO_SNDBUF
+EOF
+
+
+echo $ac_n "checking Default UDP receive buffer size""... $ac_c" 1>&6
+if test "$cross_compiling" = yes; then
+ SQUID_UDP_SO_RCVBUF=8192
+else
+cat > conftest.$ac_ext <<EOF
+#line 2206 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+main ()
+{
+ int fd,val=0,len=sizeof(int);
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(1);
+ if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) < 0) exit(1);
+ if (val <= 0) exit(1);
+ fprintf (fopen("conftestval", "w"), "%d\n", val);
+ exit(0);
+}
+
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ SQUID_UDP_SO_RCVBUF=`cat conftestval`
+else
+ SQUID_UDP_SO_RCVBUF=8192
+fi
+fi
+rm -fr conftest*
+echo "$ac_t""$SQUID_UDP_SO_RCVBUF" 1>&6
+cat >> confdefs.h <<EOF
+#define SQUID_UDP_SO_RCVBUF $SQUID_UDP_SO_RCVBUF
+EOF
+
+
+echo $ac_n "checking Default TCP send buffer size""... $ac_c" 1>&6
+if test "$cross_compiling" = yes; then
+ SQUID_TCP_SO_SNDBUF=8192
+else
+cat > conftest.$ac_ext <<EOF
+#line 2242 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+main ()
+{
+ int fd,val=0,len=sizeof(int);
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) exit(1);
+ if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) exit(1);
+ if (val <= 0) exit(1);
+ fprintf (fopen("conftestval", "w"), "%d\n", val);
+ exit(0);
+}
+
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ SQUID_TCP_SO_SNDBUF=`cat conftestval`
+else
+ SQUID_TCP_SO_SNDBUF=8192
+fi
+fi
+rm -fr conftest*
+echo "$ac_t""$SQUID_TCP_SO_SNDBUF" 1>&6
+cat >> confdefs.h <<EOF
+#define SQUID_TCP_SO_SNDBUF $SQUID_TCP_SO_SNDBUF
+EOF
+
+
+echo $ac_n "checking Default TCP receive buffer size""... $ac_c" 1>&6
+if test "$cross_compiling" = yes; then
+ SQUID_TCP_SO_RCVBUF=8192
+else
+cat > conftest.$ac_ext <<EOF
+#line 2278 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+main ()
+{
+ int fd,val=0,len=sizeof(int);
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) exit(1);
+ if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) < 0) exit(1);
+ if (val <= 0) exit(1);
+ fprintf (fopen("conftestval", "w"), "%d\n", val);
+ exit(0);
+}
+
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ SQUID_TCP_SO_RCVBUF=`cat conftestval`
+else
+ SQUID_TCP_SO_RCVBUF=8192
+fi
+fi
+rm -fr conftest*
+echo "$ac_t""$SQUID_TCP_SO_RCVBUF" 1>&6
+cat >> confdefs.h <<EOF
+#define SQUID_TCP_SO_RCVBUF $SQUID_TCP_SO_RCVBUF
+EOF
+
+
+echo $ac_n "checking if sys_errlist is already defined""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 2311 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main() { return 0; }
+int t() {
+char *s = sys_errlist[0];
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+cat >> confdefs.h <<\EOF
+#define NEED_SYS_ERRLIST 1
+EOF
+
+fi
+rm -f conftest*
+
+
XTRA_OBJS=''
if test "$HAVE_LIBMALLOC" = "yes" ; then
if test -r /usr/lib/debug/malloc.o ; then
LIBS=''
-if test -z "$STD_CFLAGS"; then
- STD_CFLAGS="-g"
- XXXCC=`echo $CC | awk '{print $1}'`
- if test "`basename $XXXCC`" = "gcc"; then
- case "$host" in
- *-sun-sunos*)
- # sunos has too many warnings for this to be useful
- ;;
- *)
- STD_CFLAGS="$STD_CFLAGS -Wall"
- ;;
- esac
- fi
-fi
-
-
-if test -z "$STD_LDFLAGS"; then
- STD_LDFLAGS="-g"
-fi
-
-
-case "$host" in
- *-sgi-irix*)
- echo "Adding ANSI compile flags for IRIX..."
- XXXCC=`echo $CC | awk '{print $1}'`
- if test "`basename $XXXCC`" = "gcc"; then
- XTRA_CFLAGS="$XTRA_CFLAGS -ansi"
- else
- XTRA_CFLAGS="$XTRA_CFLAGS -D__STRICT_ANSI__"
- fi
- ;;
- *-hp-hpux*)
- echo "Disabling 'ranlib' for HP-UX..."
- RANLIB=":"
- ;;
-esac
-
rm -f core
s%@host_cpu@%$host_cpu%g
s%@host_vendor@%$host_vendor%g
s%@host_os@%$host_os%g
-s%@XTRA_CFLAGS@%$XTRA_CFLAGS%g
s%@CACHE_HTTP_PORT@%$CACHE_HTTP_PORT%g
s%@CACHE_ICP_PORT@%$CACHE_ICP_PORT%g
s%@CACHE_FTP_PORT@%$CACHE_FTP_PORT%g
s%@CRYPT_LIB@%$CRYPT_LIB%g
s%@XTRA_OBJS@%$XTRA_OBJS%g
s%@XTRA_LIBS@%$XTRA_LIBS%g
-s%@STD_CFLAGS@%$STD_CFLAGS%g
-s%@STD_LDFLAGS@%$STD_LDFLAGS%g
CEOF
EOF
dnl
dnl Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9)
dnl
-dnl $Id: configure.in,v 1.20 1996/05/03 22:56:16 wessels Exp $
+dnl $Id: configure.in,v 1.21 1996/07/09 03:41:04 wessels Exp $
dnl
dnl
dnl
AC_INIT(src/main.c)
AC_CONFIG_HEADER(include/autoconf.h)
-AC_REVISION($Revision: 1.20 $)dnl
+AC_REVISION($Revision: 1.21 $)dnl
AC_PREFIX_DEFAULT(/usr/local/squid)
AC_CONFIG_AUX_DIR(aux)
AC_CANONICAL_HOST
-XTRA_CFLAGS=''
CRYPT_LIB=''
dnl use directory structure of cached as default (hack)
fi
dnl Subsitutions
-AC_SUBST(XTRA_CFLAGS)
AC_SUBST(CACHE_HTTP_PORT)
AC_SUBST(CACHE_ICP_PORT)
AC_SUBST(CACHE_FTP_PORT)
+AC_DEFINE_UNQUOTED(CONFIG_HOST_TYPE, "$host")
+
+dnl Set default LDFLAGS
+if test -z "$LDFLAGS"; then
+ LDFLAGS="-g"
+fi
+
+PREST_CFLAGS="$CFLAGS"
+
dnl Check for GNU cc
AC_PROG_CC
sleep 5
fi
+dnl Set Default CFLAGS
+if test -z "$PRESET_CFLAGS"; then
+ if test "$GCC" = "yes"; then
+ case "$host" in
+ *-sun-sunos*|*m88k*)
+ # sunos has too many warnings for this to be useful
+ # motorola too
+ ;;
+ *)
+ CFLAGS="$CFLAGS -Wall"
+ ;;
+ esac
+ fi
+
+ dnl Check if ANSI compile options are needed
+ dnl
+ case "$host" in
+ *-sgi-irix*)
+ echo "Adding ANSI compile flags for IRIX..."
+ if test "$GCC" = "yes"; then
+ [CFLAGS="$CFLAGS -ansi"]
+ else
+ [CFLAGS="$CFLAGS -D__STRICT_ANSI__"]
+ fi
+ ;;
+ *-hp-hpux*)
+ echo "Disabling 'ranlib' for HP-UX..."
+ RANLIB=":"
+ ;;
+ esac
+fi
+
+dnl Set LDFLAGS
+if test -z "$PRESET_LDFLAGS"; then
+ if test "$GCC" = "yes"; then
+ case "$host" in
+ *)
+ # nothing
+ ;;
+ esac
+ fi
+fi
dnl Check for programs
AC_PROG_CPP
AC_CHECK_HEADERS( \
alloca.h \
arpa/inet.h \
+ arpa/nameser.h \
bstring.h \
config.h \
crypt.h \
+ ctype.h \
+ errno.h \
fcntl.h \
+ grp.h \
+ libc.h \
+ malloc.h \
memory.h \
+ netdb.h \
netinet/in.h \
+ netinet/tcp.h \
+ pwd.h \
+ regex.h \
+ resolv.h \
+ signal.h \
+ stdarg.h \
+ stddef.h \
+ stdio.h \
stdlib.h \
string.h \
strings.h \
sys/file.h \
+ sys/param.h \
+ sys/resource.h \
sys/select.h\
+ sys/socket.h \
+ sys/stat.h \
+ sys/syscall.h \
sys/time.h \
sys/types.h \
- sys/syscall.h \
- unistd.h \
- regex.h \
+ sys/un.h \
+ sys/wait.h \
syslog.h \
+ time.h \
+ unistd.h \
+ varargs.h \
)
AC_MSG_CHECKING(for tm->tm_gmtoff)
AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no))
-AC_MSG_CHECKING(if signal handlers need to be reset)
-AC_TRY_RUN([void handle(s) int s; { return; }
-main(){signal(15,handle);kill(getpid(),15);kill(getpid(),15);exit(0);}],
-AC_MSG_RESULT(no),
-[AC_DEFINE(RESET_SIGNAL_HANDLER)
-AC_MSG_RESULT(yes)],
-dnl default
-[AC_DEFINE(RESET_SIGNAL_HANDLER)
-AC_MSG_RESULT(yes)],)
-
dnl Check for typedefs
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_FUNC_ALLOCA
dnl Check for needed libraries
+AC_CHECK_LIB(nsl, main)
AC_CHECK_LIB(socket, main)
AC_CHECK_LIB(malloc, main, [HAVE_LIBMALLOC="yes"; LIBS="$LIBS -lmalloc"])
-AC_CHECK_LIB(nsl, main)
AC_CHECK_LIB(resolv, main)
AC_CHECK_LIB(bsd, main)
echo "Removing -lnsl for IRIX..."
LIBS=`echo $LIBS | sed -e s/-lnsl//`
;;
+ *m88k*)
+ CFLAGS="$CFLAGS -D_SQUID_MOTOROLA_"
+ ;;
+
esac
dnl Check for library functions
AC_CHECK_FUNCS(\
+ bcopy \
getdtablesize \
+ getrusage \
+ lrand48 \
mallinfo \
mallopt \
+ memmove \
regcomp \
regexec \
regfree \
+ res_init \
seteuid \
+ setpgrp \
setresuid \
setrlimit \
+ setsid \
+ sigaction \
+ socketpair \
+ srand48 \
strdup \
- strerror \
sysconf \
syslog \
+ tempnam \
timegm \
)
AC_MSG_CHECKING(Maximum number of filedescriptors we can open)
AC_TRY_RUN([
#include <unistd.h>
+#include <sys/time.h> /* needed on FreeBSD */
#include <sys/param.h>
#include <sys/resource.h>
main() {
AC_MSG_RESULT($SQUID_FD_SETSIZE)
AC_DEFINE_UNQUOTED(SQUID_FD_SETSIZE, $SQUID_FD_SETSIZE)
+AC_MSG_CHECKING(Default UDP send buffer size)
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+main ()
+{
+ int fd,val=0,len=sizeof(int);
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(1);
+ if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) exit(1);
+ if (val<=0) exit(1);
+ fprintf (fopen("conftestval", "w"), "%d\n", val);
+ exit(0);
+}
+],
+SQUID_UDP_SO_SNDBUF=`cat conftestval`,
+SQUID_UDP_SO_SNDBUF=8192,
+SQUID_UDP_SO_SNDBUF=8192)
+AC_MSG_RESULT($SQUID_UDP_SO_SNDBUF)
+AC_DEFINE_UNQUOTED(SQUID_UDP_SO_SNDBUF, $SQUID_UDP_SO_SNDBUF)
+
+AC_MSG_CHECKING(Default UDP receive buffer size)
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+main ()
+{
+ int fd,val=0,len=sizeof(int);
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(1);
+ if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) < 0) exit(1);
+ if (val <= 0) exit(1);
+ fprintf (fopen("conftestval", "w"), "%d\n", val);
+ exit(0);
+}
+],
+SQUID_UDP_SO_RCVBUF=`cat conftestval`,
+SQUID_UDP_SO_RCVBUF=8192,
+SQUID_UDP_SO_RCVBUF=8192)
+AC_MSG_RESULT($SQUID_UDP_SO_RCVBUF)
+AC_DEFINE_UNQUOTED(SQUID_UDP_SO_RCVBUF, $SQUID_UDP_SO_RCVBUF)
+
+AC_MSG_CHECKING(Default TCP send buffer size)
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+main ()
+{
+ int fd,val=0,len=sizeof(int);
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) exit(1);
+ if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) exit(1);
+ if (val <= 0) exit(1);
+ fprintf (fopen("conftestval", "w"), "%d\n", val);
+ exit(0);
+}
+],
+SQUID_TCP_SO_SNDBUF=`cat conftestval`,
+SQUID_TCP_SO_SNDBUF=8192,
+SQUID_TCP_SO_SNDBUF=8192)
+AC_MSG_RESULT($SQUID_TCP_SO_SNDBUF)
+AC_DEFINE_UNQUOTED(SQUID_TCP_SO_SNDBUF, $SQUID_TCP_SO_SNDBUF)
+
+AC_MSG_CHECKING(Default TCP receive buffer size)
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+main ()
+{
+ int fd,val=0,len=sizeof(int);
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) exit(1);
+ if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) < 0) exit(1);
+ if (val <= 0) exit(1);
+ fprintf (fopen("conftestval", "w"), "%d\n", val);
+ exit(0);
+}
+],
+SQUID_TCP_SO_RCVBUF=`cat conftestval`,
+SQUID_TCP_SO_RCVBUF=8192,
+SQUID_TCP_SO_RCVBUF=8192)
+AC_MSG_RESULT($SQUID_TCP_SO_RCVBUF)
+AC_DEFINE_UNQUOTED(SQUID_TCP_SO_RCVBUF, $SQUID_TCP_SO_RCVBUF)
+
+AC_MSG_CHECKING(if sys_errlist[] is already defined)
+AC_TRY_COMPILE([#include <stdio.h>],
+[char *s = sys_errlist[0];],
+AC_MSG_RESULT(yes),
+[AC_MSG_RESULT(no)
+AC_DEFINE(NEED_SYS_ERRLIST)])
+
dnl Need the debugging version of malloc if available
XTRA_OBJS=''
if test "$HAVE_LIBMALLOC" = "yes" ; then
LIBS=''
AC_SUBST(XTRA_LIBS)
-dnl Set STD_CFLAGS
-if test -z "$STD_CFLAGS"; then
- STD_CFLAGS="-g"
- XXXCC=`echo $CC | awk '{print $1}'`
- if test "`basename $XXXCC`" = "gcc"; then
- case "$host" in
- *-sun-sunos*)
- # sunos has too many warnings for this to be useful
- ;;
- *)
- STD_CFLAGS="$STD_CFLAGS -Wall"
- ;;
- esac
- fi
-fi
-AC_SUBST(STD_CFLAGS)
-
-dnl Set STD_LDFLAGS
-if test -z "$STD_LDFLAGS"; then
- STD_LDFLAGS="-g"
-fi
-AC_SUBST(STD_LDFLAGS)
-
-dnl Last minute system specific modifications
-dnl
-case "$host" in
- *-sgi-irix*)
- echo "Adding ANSI compile flags for IRIX..."
- XXXCC=`echo $CC | awk '{print $1}'`
- if test "`basename $XXXCC`" = "gcc"; then
- [XTRA_CFLAGS="$XTRA_CFLAGS -ansi"]
- else
- [XTRA_CFLAGS="$XTRA_CFLAGS -D__STRICT_ANSI__"]
- fi
- ;;
- *-hp-hpux*)
- echo "Disabling 'ranlib' for HP-UX..."
- RANLIB=":"
- ;;
-esac
-
dnl Clean up after OSF/1 core dump bug
rm -f core
--- /dev/null
+Caching Code
+ Successful 2xx
+c 200 OK
+ 201 Created
+ 202 Accepted
+c 203 Non-Authoriative Information *
+E 204 No Content
+ 205 Reset Content *
+ 206 Partial Content *
+ Redirection 3xx
+C 300 Multiple Choices
+C 301 Moved Permanently
+t 302 Moved Temporarily
+- 303 See Other *
+- 304 Not Modified
+E 305 Use Proxy (proxy redirect) *
+ Client Error 4xx
+E 400 Bad Request
+- 401 Unauthorized
+ 402 Payment Required *
+E 403 Forbidden
+E 404 Not Found
+E 405 Method Not Allowed *
+ 406 Not Acceptable *
+- 407 Proxy Authentication Required *
+ 408 Request Timeout *
+ 409 Confict *
+C 410 Gone *
+ 411 Length Required *
+ 412 Precondition Failed *
+ 413 Request Entity To Large *
+E 414 Request-URI Too Long *
+ 415 Unsupported Media Type
+ Server Error 5xx
+E 500 Internal Server Error
+E 501 Not Implemented
+E 502 Bad Gateway
+E 503 Service Unavailable
+E 504 Gateway Timeout *
+ 505 HTTP Version Not Supported *
+
+Notes:
+* HTTP 1.1
+c Cached unless a query response without expiry information
+C Cached
+E Negatively cached if no expiry headers.
+t Cached only if expiry information
+- Not cached
+
+Unless other said, the response code is not cached.
/* Define if struct mallinfo has mxfast member */
#undef HAVE_EXT_MALLINFO
-/* Define if signal handlers must be reset after invocation */
-#undef RESET_SIGNAL_HANDLER
-
/* Maximum number of open filedescriptors */
#undef SQUID_FD_SETSIZE
+/* UDP send buffer size */
+#undef SQUID_UDP_SO_SNDBUF
+
+/* UDP receive buffer size */
+#undef SQUID_UDP_SO_RCVBUF
+
+/* TCP send buffer size */
+#undef SQUID_TCP_SO_SNDBUF
+
+/* TCP receive buffer size */
+#undef SQUID_TCP_SO_RCVBUF
+
+/* Host type from configure */
+#undef CONFIG_HOST_TYPE
+
+/* If we need to declare sys_errlist[] as external */
+#undef NEED_SYS_ERRLIST
+
/* The number of bytes in a int. */
#undef SIZEOF_INT
/* The number of bytes in a long. */
#undef SIZEOF_LONG
+/* Define if you have the bcopy function. */
+#undef HAVE_BCOPY
+
/* Define if you have the getdtablesize function. */
#undef HAVE_GETDTABLESIZE
+/* Define if you have the getrusage function. */
+#undef HAVE_GETRUSAGE
+
+/* Define if you have the lrand48 function. */
+#undef HAVE_LRAND48
+
/* Define if you have the mallinfo function. */
#undef HAVE_MALLINFO
/* Define if you have the mallopt function. */
#undef HAVE_MALLOPT
+/* Define if you have the memmove function. */
+#undef HAVE_MEMMOVE
+
/* Define if you have the regcomp function. */
#undef HAVE_REGCOMP
/* Define if you have the regfree function. */
#undef HAVE_REGFREE
+/* Define if you have the res_init function. */
+#undef HAVE_RES_INIT
+
/* Define if you have the seteuid function. */
#undef HAVE_SETEUID
+/* Define if you have the setpgrp function. */
+#undef HAVE_SETPGRP
+
/* Define if you have the setresuid function. */
#undef HAVE_SETRESUID
/* Define if you have the setrlimit function. */
#undef HAVE_SETRLIMIT
+/* Define if you have the setsid function. */
+#undef HAVE_SETSID
+
+/* Define if you have the sigaction function. */
+#undef HAVE_SIGACTION
+
+/* Define if you have the socketpair function. */
+#undef HAVE_SOCKETPAIR
+
+/* Define if you have the srand48 function. */
+#undef HAVE_SRAND48
+
/* Define if you have the strdup function. */
#undef HAVE_STRDUP
-/* Define if you have the strerror function. */
-#undef HAVE_STRERROR
-
/* Define if you have the sysconf function. */
#undef HAVE_SYSCONF
/* Define if you have the syslog function. */
#undef HAVE_SYSLOG
+/* Define if you have the tempnam function. */
+#undef HAVE_TEMPNAM
+
/* Define if you have the timegm function. */
#undef HAVE_TIMEGM
/* Define if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
+/* Define if you have the <arpa/nameser.h> header file. */
+#undef HAVE_ARPA_NAMESER_H
+
/* Define if you have the <bstring.h> header file. */
#undef HAVE_BSTRING_H
/* Define if you have the <crypt.h> header file. */
#undef HAVE_CRYPT_H
+/* Define if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
+/* Define if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
+/* Define if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* Define if you have the <libc.h> header file. */
+#undef HAVE_LIBC_H
+
+/* Define if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
/* Define if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define if you have the <ndir.h> header file. */
#undef HAVE_NDIR_H
+/* Define if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
/* Define if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
+/* Define if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
+/* Define if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
/* Define if you have the <regex.h> header file. */
#undef HAVE_REGEX_H
+/* Define if you have the <resolv.h> header file. */
+#undef HAVE_RESOLV_H
+
+/* Define if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the <sys/ndir.h> header file. */
#undef HAVE_SYS_NDIR_H
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
/* Define if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
+/* Define if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
/* Define if you have the <sys/syscall.h> header file. */
#undef HAVE_SYS_SYSCALL_H
/* Define if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
+/* Define if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
/* Define if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
+/* Define if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define if you have the <varargs.h> header file. */
+#undef HAVE_VARARGS_H
+
/* Define if you have the bsd library (-lbsd). */
#undef HAVE_LIBBSD
--- /dev/null
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _TEMPNAM_H
+#define _TEMPNAM_H
+extern char *tempnam (const char *, const char *);
+#endif /* _TEMPNAM_H */
/*
- * $Id: util.h,v 1.6 1996/04/14 03:34:28 wessels Exp $
+ * $Id: util.h,v 1.7 1996/07/09 03:41:08 wessels Exp $
+ *
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
*/
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#ifndef _UTIL_H_
#define _UTIL_H_
#if !defined(SQUIDHOSTNAMELEN)
#include <sys/param.h>
+#ifndef _SQUID_NETDB_H_ /* need protection on NEXTSTEP */
+#define _SQUID_NETDB_H_
#include <netdb.h>
+#endif
#if !defined(MAXHOSTNAMELEN) || (MAXHOSTNAMELEN < 128)
#define SQUIDHOSTNAMELEN 128
#else
#ifndef _PARAMS
#if defined(__STDC__) || defined(__cplusplus) || defined(__STRICT_ANSI__)
#define _PARAMS(ARGS) ARGS
-#else /* Traditional C */
-#define _PARAMS(ARGS) ()
-#endif /* __STDC__ */
-#endif /* _PARAMS */
+#else /* Traditional C */
+#define _PARAMS(ARGS) ()
+#endif /* __STDC__ */
+#endif /* _PARAMS */
-#ifdef NO_STRDUP
-char *strdup _PARAMS((char *)); /* Duplicate a string */
+#if !HAVE_STRDUP
+extern char *strdup _PARAMS((char *));
#endif
-char *xstrdup _PARAMS((char *)); /* Duplicate a string */
+extern char *xstrdup _PARAMS((char *)); /* Duplicate a string */
/* from xmalloc.c */
-void *xmalloc _PARAMS((size_t)); /* Wrapper for malloc(3) */
+void *xmalloc _PARAMS((size_t)); /* Wrapper for malloc(3) */
void *xrealloc _PARAMS((void *, size_t)); /* Wrapper for realloc(3) */
-void *xcalloc _PARAMS((int, size_t)); /* Wrapper for calloc(3) */
-void xfree _PARAMS((void *)); /* Wrapper for free(3) */
-void xxfree _PARAMS((void *)); /* Wrapper for free(3) */
-char *xstrdup _PARAMS ((char *));
-char *xstrerror _PARAMS(());
-
-char *getfullhostname _PARAMS(());
+void *xcalloc _PARAMS((int, size_t)); /* Wrapper for calloc(3) */
+void xfree _PARAMS((void *)); /* Wrapper for free(3) */
+void xxfree _PARAMS((void *)); /* Wrapper for free(3) */
+char *xstrdup _PARAMS((char *));
+char *xstrerror _PARAMS((void));
+char *getfullhostname _PARAMS((void));
+void xmemcpy _PARAMS((void *, void*, int));
+
+#if XMALLOC_STATISTICS
+void malloc_statistics _PARAMS((void (*)(int, int, void *), void *));
+#endif
/* from debug.c */
#ifndef MAX_DEBUG_LEVELS
#ifndef MAIN
extern int Harvest_do_debug;
extern int Harvest_debug_levels[];
-#endif /* MAIN */
+#endif /* MAIN */
#undef debug_ok_fast
#if USE_NO_DEBUGGING
{if (debug_ok_fast((section),(level))) {Log X;}}
#endif
-void debug_reset _PARAMS((void));
+void debug_flag _PARAMS((char *));
+#ifdef UNUSED_CODE
void debug_enable _PARAMS((int, int));
void debug_disable _PARAMS((int));
-void debug_flag _PARAMS((char *));
-int debug_ok _PARAMS((int, int));
+void debug_reset _PARAMS((void));
+int debug_ok _PARAMS((int, int));
+#endif /* UNUSED_CODE */
#define HOST_CACHE_TTL 3600
typedef struct _host {
- char key[SQUIDHOSTNAMELEN]; /* www.bar.com */
- char fqdn[SQUIDHOSTNAMELEN]; /* real.bar.com */
- char dotaddr[16]; /* 128.138.213.10 */
- char ipaddr[4];
- time_t last_t; /* last access of this info */
- int n; /* # of requests for this host */
- int addrlen; /* length of 'ipaddr', always 4 */
+ char key[SQUIDHOSTNAMELEN]; /* www.bar.com */
+ char fqdn[SQUIDHOSTNAMELEN]; /* real.bar.com */
+ char dotaddr[16]; /* 128.138.213.10 */
+ char ipaddr[4];
+ time_t last_t; /* last access of this info */
+ int n; /* # of requests for this host */
+ int addrlen; /* length of 'ipaddr', always 4 */
struct _host *next;
} Host;
-extern Host *thisHost;
-
-void host_cache_init _PARAMS((void));
-Host *get_host _PARAMS((char *hostname));
-int delete_host _PARAMS((Host *h));
-int expire_host_cache _PARAMS((time_t timeout));
-void dump_host_cache _PARAMS((int, int));
-
+extern Host *thisHost;
+Host *get_host _PARAMS((char *hostname));
+int delete_host _PARAMS((Host * h));
+int expire_host_cache _PARAMS((time_t timeout));
+#ifdef UNUSED_CODE
+void dump_host_cache _PARAMS((int, int));
+#endif
char *mkhttpdlogtime _PARAMS((time_t *));
extern char *mkrfc850 _PARAMS((time_t *));
extern time_t parse_rfc850 _PARAMS((char *str));
-extern void init_log3 _PARAMS((char *pn, FILE *a, FILE *b));
+extern void init_log3 _PARAMS((char *pn, FILE * a, FILE * b));
extern void debug_init();
extern void log_errno2 _PARAMS((char *, int, char *));
#if defined(__STRICT_ANSI__)
-extern void Log _PARAMS((char *, ...));
-extern void errorlog _PARAMS((char *, ...));
+extern void Log _PARAMS((char *,...));
+extern void errorlog _PARAMS((char *,...));
#else
-extern void Log ();
-extern void errorlog ();
+extern void Log();
+extern void errorlog();
#endif /* __STRICT_ANSI__ */
-#include "autoconf.h" /* get the #defines from GNU autoconf */
/* Extended regular expression matching and search library,
version 0.12.
(Implements POSIX draft P10003.2/D11.2, except for
#define _GNU_SOURCE
-/* We need this for `regex.h', and perhaps for the Emacs include files. */
-#include <sys/types.h>
-
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#if !HAVE_ALLOCA
#define REGEX_MALLOC 1
DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
\
/* Restore register info. */ \
- high_reg = (unsigned) POP_FAILURE_ITEM (); \
+ high_reg = (unsigned long) POP_FAILURE_ITEM (); \
DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \
\
- low_reg = (unsigned) POP_FAILURE_ITEM (); \
+ low_reg = (unsigned long) POP_FAILURE_ITEM (); \
DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \
\
for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
unsigned num_regs = bufp->re_nsub + 1;
/* The currently active registers. */
- unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
- unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+ unsigned long lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ unsigned long highest_active_reg = NO_HIGHEST_ACTIVE_REG;
/* Information on the contents of registers. These are pointers into
the input strings; they record just what was matched (on this
matching and the regnum-th regend points to right after where we
stopped matching the regnum-th subexpression. (The zeroth register
keeps track of what the whole pattern matches.) */
- const char **regstart, **regend;
+ const char **regstart = NULL, **regend = NULL;
/* If a group that's operated upon by a repetition operator fails to
match anything, then the register for its start will need to be
restored because it will have been set to wherever in the string we
are when we last see its open-group operator. Similarly for a
register's end. */
- const char **old_regstart, **old_regend;
+ const char **old_regstart = NULL, **old_regend = NULL;
/* The is_active field of reg_info helps us keep track of which (possibly
nested) subexpressions we are currently in. The matched_something
matched any of the pattern so far this time through the reg_num-th
subexpression. These two fields get reset each time through any
loop their register is in. */
- register_info_type *reg_info;
+ register_info_type *reg_info = NULL;
/* The following record the register info as found in the above
variables when we find a match better than any we've seen before.
This happens as we backtrack through the failure points, which in
turn happens only if we have not yet matched the entire string. */
unsigned best_regs_set = false;
- const char **best_regstart, **best_regend;
+ const char **best_regstart = NULL, **best_regend = NULL;
/* Logically, this is `best_regend[0]'. But we don't want to have to
allocate space for that if we're not allocating space for anything
const char *match_end = NULL;
/* Used when we pop values we don't care about. */
- const char **reg_dummy;
- register_info_type *reg_info_dummy;
+ const char **reg_dummy = NULL;
+ register_info_type *reg_info_dummy = NULL;
#ifdef DEBUG
/* Counts the total number of registers pushed. */
regstart[r] = old_regstart[r];
/* xx why this test? */
- if ((int) old_regend[r] >= (int) regstart[r])
+ if ((long) old_regend[r] >= (long) regstart[r])
regend[r] = old_regend[r];
}
}
p1++;
EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+ PUSH_FAILURE_POINT ( p1 + mcnt, d, -2);
goto fail;
}
actual values. Otherwise, we will restore only one
register from the stack, since lowest will == highest in
`pop_failure_point'. */
- unsigned dummy_low_reg, dummy_high_reg;
+ unsigned long dummy_low_reg, dummy_high_reg;
unsigned char *pdummy;
const char *sdummy;
#
# Darren Hardy, hardy@cs.colorado.edu, April 1994
#
-# $Id: Makefile.in,v 1.8 1996/05/01 22:36:21 wessels Exp $
+# $Id: Makefile.in,v 1.9 1996/07/09 03:41:10 wessels Exp $
#
prefix = @prefix@
srcdir = @srcdir@
INSTALL_BIN = @INSTALL_PROGRAM@
INSTALL_FILE = @INSTALL_DATA@
RANLIB = @RANLIB@
-STD_CFLAGS = @STD_CFLAGS@
-STD_LDFLAGS = @STD_LDFLAGS@
+AC_CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
XTRA_LIBS = @XTRA_LIBS@
-XTRA_CFLAGS = @XTRA_CFLAGS@
INCLUDE = -I../include -I$(srcdir)/../include
UTILOBJS = rfc850.o \
host_cache.o \
getfullhostname.o \
debug.o \
- log.o
+ log.o \
+ tempnam.o
REGEXOBJS = GNUregex.o
-LIBS = libutil.a libregex.a
+LIBS = libmiscutil.a libregex.a
-CFLAGS = $(STD_CFLAGS) $(XTRA_CFLAGS) $(INCLUDE)
-LDFLAGS = $(STD_LDFLAGS)
+CFLAGS = $(AC_CFLAGS) $(INCLUDE)
all: $(LIBS)
-libutil.a: $(UTILOBJS)
+libmiscutil.a: $(UTILOBJS)
ar r $@ $(UTILOBJS)
$(RANLIB) $@
+/*
+ * $Id: getfullhostname.c,v 1.5 1996/07/09 03:41:11 wessels Exp $
+ *
+ * DEBUG:
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
-/* $Id: getfullhostname.c,v 1.4 1996/04/14 03:25:23 wessels Exp $ */
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
+#include "config.h"
+
+#if HAVE_STDIO_H
#include <stdio.h>
+#endif
+#if HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
#include <string.h>
+#endif
+#if HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
+#if HAVE_SYS_TYPES_H
#include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
+#endif
+#if HAVE_NETINET_IN_H
#include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
+#endif
+#if HAVE_NETDB_H && !defined(_SQUID_NETDB_H_) /* protect on NEXTSTEP */
+#define _SQUID_NETDB_H_
#include <netdb.h>
-#include "util.h"
+#endif
+#include "util.h"
/*
* getfullhostname() - Returns the fully qualified name of the current
-/* $Id: rfc1738.c,v 1.2 1996/02/29 08:15:23 wessels Exp $ */
+/*
+ * $Id: rfc1738.c,v 1.3 1996/07/09 03:41:13 wessels Exp $
+ *
+ * DEBUG:
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
+
+#include "config.h"
+#if HAVE_STDIO_H
#include <stdio.h>
+#endif
+#if HAVE_STRING_H
#include <string.h>
+#endif
+
#include "util.h"
#define BIG_BUFSIZ (BUFSIZ * 4)
* RFC 1738 defines that these characters should be escaped, as well
* any non-US-ASCII character or anything between 0x00 - 0x1F.
*/
-char rfc1738_unsafe_chars[] =
+static char rfc1738_unsafe_chars[] =
{
(char) 0x3C, /* < */
(char) 0x3E, /* > */
}
}
/* RFC 1738 says any control chars (0x00-0x1F) are encoded */
- if ((*p >= (char) 0x00) && (*p <= (char) 0x1F)) {
+ if (*p <= (char) 0x1F) {
do_escape = 1;
}
/* RFC 1738 says 0x7f is encoded */
--- /dev/null
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the GNU C Library; see the file COPYING.LIB. If
+ * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+ * Cambridge, MA 02139, USA. */
+
+/* tempnam for NEXTSTEP. from Linux GNU libc. Hacked by lukeh@schnet.edu.au */
+
+#include "config.h"
+
+#if !HAVE_TEMPNAM
+
+#ifdef __NeXT__
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE
+#endif /* _POSIX_SOURCE_ */
+#if HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#endif /* __NeXT__ */
+
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef __STDC__
+#if HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define P_tmpdir "/tmp"
+
+/* These are the characters used in temporary filenames. */
+static const char letters[] =
+
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+/* Return nonzero if DIR is an existent directory. */
+static int diraccess (const char *dir) {
+ struct stat buf;
+ uid_t euid;
+
+ if (stat(dir, &buf) != 0 || !S_ISDIR(buf.st_mode))
+ return 0;
+
+ /* That is going to be tough. */
+
+ euid = geteuid();
+
+ /* super user */
+ if (!euid)
+ return 1;
+
+ if (euid == buf.st_uid)
+ return ((buf.st_mode & S_IWUSR) && (buf.st_mode & S_IXUSR));
+
+ if (getegid() == buf.st_gid)
+ return ((buf.st_mode & S_IWGRP) && (buf.st_mode & S_IXGRP));
+
+ return ((buf.st_mode & S_IWOTH) && (buf.st_mode & S_IXOTH));
+}
+
+/* Return nonzero if FILE exists. */
+static int exists(const char *file) {
+ /* We can stat the file even if we can't read its data. */
+ struct stat st;
+ int save = errno;
+ if (stat(file, &st) == 0)
+ return 1;
+ else {
+ /* We report that the file exists if stat failed for a
+ * reason other
+ * than nonexistence. In this case, it may or may not exist, and
+ * we
+ * don't know; but reporting that it does exist will never cause
+ * any
+ * trouble, while reporting that it doesn't exist when it does
+ * would
+ * violate the interface of __stdio_gen_tempname. */
+ int exists = errno != ENOENT;
+ errno = save;
+ return exists;
+ }
+}
+
+
+/* Generate a temporary filename and return it (in a static buffer). If
+ STREAMPTR is not NULL, open a stream "w+b" on the file and set
+ *STREAMPTR to it. If DIR_SEARCH is nonzero, DIR and PFX are used as
+ described for tempnam. If not, a temporary filename in P_tmpdir with
+ no special prefix is generated. If LENPTR is not NULL, *LENPTR is
+ set the to length (including the terminating '\0') of the resultant
+ filename, which is returned. This goes through a cyclic pattern of
+ all possible filenames consisting of five decimal digits of the
+ current pid and three of the characters in `letters'. Data for
+ tempnam and tmpnam is kept separate, but when tempnam is using
+ P_tmpdir and no prefix (i.e, it is identical to tmpnam), the same
+ data is used. Each potential filename is tested for an
+ already-existing file of the same name, and no name of an existing
+ file will be returned. When the cycle reaches its end (12345ZZZ),
+ NULL is returned. */
+
+static char *gen_tempname (
+ const char *dir,
+ const char *pfx,
+ int dir_search,
+ size_t * lenptr,
+ FILE ** streamptr
+) {
+ int saverrno = errno;
+ static const char tmpdir[] = P_tmpdir;
+ static struct {
+ unsigned char digits[4];
+ } infos[2], *info;
+ static char buf[FILENAME_MAX];
+ static pid_t oldpid = (pid_t) 0;
+ pid_t pid = getpid();
+ register size_t len, plen, dlen, flen;
+ int i, carry;
+
+ if (dir_search) {
+ register const char *d = getenv("TMPDIR");
+ if (d != NULL && !diraccess(d))
+ d = NULL;
+ if (d == NULL && dir != NULL && diraccess(dir))
+ d = dir;
+ if (d == NULL && diraccess(tmpdir))
+ d = tmpdir;
+ if (d == NULL && diraccess("/tmp"))
+ d = "/tmp";
+ if (d == NULL) {
+ errno = ENOENT;
+ return NULL;
+ }
+ dir = d;
+ } else
+ dir = tmpdir;
+ dlen = strlen(dir);
+
+ /* Remove trailing slashes from the directory name. */
+ while (dlen > 1 && dir[dlen - 1] == '/')
+ --dlen;
+
+ if (pfx != NULL && *pfx != '\0') {
+ plen = strlen(pfx);
+ if (plen > 5)
+ plen = 5;
+ } else
+ plen = 0;
+
+ if (dir != tmpdir && !strcmp(dir, tmpdir))
+ dir = tmpdir;
+ info = &infos[(plen == 0 && dir == tmpdir) ? 1 : 0];
+
+ if (pid != oldpid) {
+ oldpid = pid;
+ for (i = 0; i < sizeof(info->digits); i++)
+ infos[0].digits[i] = infos[1].digits[i] = 0;
+ }
+ flen = dlen + 1 + plen + 5;
+ for (;;) {
+ if (info->digits[sizeof(info->digits) - 1]) {
+ errno = EEXIST;
+ return NULL;
+ }
+ len = flen;
+ if ((sizeof(buf) - sizeof(info->digits)) < len ||
+ sprintf(buf, "%.*s/%.*s%.5d", (int) dlen, dir,
+ (int) plen, pfx, pid % 100000) != (int) len)
+ return NULL;
+
+ /* Get the last part of string */
+ for (i = 0; i < sizeof(info->digits) - 1; i++)
+ buf[len++] = letters[info->digits[i]];
+ buf[len] = '\0';
+
+ /* Always return a unique string. */
+ carry = ++info->digits[0] / (sizeof(letters) - 1);
+ info->digits[0] %= (sizeof(letters) - 1);
+ for (i = 1; i < sizeof(info->digits); i++) {
+ info->digits[i] += carry;
+ carry = info->digits[i] / (sizeof(letters) - 1);
+ info->digits[i] %= (sizeof(letters) - 1);
+ }
+
+ if (streamptr != NULL) {
+ int fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666);
+ if (fd >= 0) {
+ *streamptr = fdopen(fd, "w+b");
+ if (*streamptr == NULL) {
+ int save = errno;
+ (void) close(fd);
+ errno = save;
+ return NULL;
+ }
+ break;
+ }
+ } else if (!exists(buf))
+ break;
+ }
+
+ errno = saverrno;
+
+ if (lenptr != NULL)
+ *lenptr = len + 1;
+ return buf;
+}
+
+char *tempnam(const char *dir, const char *pfx) {
+ size_t len;
+ register char *s;
+ register char *t = gen_tempname(dir, pfx, 1, &len, (FILE **)
+ NULL);
+
+ if (t == NULL)
+ return NULL;
+
+ s = (char *) malloc(len);
+ if (s == NULL)
+ return NULL;
+
+ (void) memcpy(s, t, len);
+ return s;
+}
+
+#endif /* !HAVE_TEMPNAM */
-/* $Id: util.c,v 1.7 1996/05/03 22:56:18 wessels Exp $ */
+/*
+ * $Id: util.c,v 1.8 1996/07/09 03:41:14 wessels Exp $
+ *
+ * DEBUG:
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
+#include "config.h"
+
+#if HAVE_STDIO_H
#include <stdio.h>
+#endif
+#if HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
#include <string.h>
+#endif
+#if HAVE_UNISTD_H
#include <unistd.h>
-#ifndef _SQUID_FREEBSD_ /* "Obsolete" Markus Stumpf <maex@Space.NET> */
+#endif
+#if HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_)
#include <malloc.h>
#endif
+#if HAVE_ERRNO_H
#include <errno.h>
+#endif
-void (*failure_notify) () = NULL;
+#include "util.h"
+
+void (*failure_notify) _PARAMS((char *)) = NULL;
static char msg[128];
extern int sys_nerr;
-#if !defined(__FreeBSD__) && !defined(__NetBSD__)
+#if NEED_SYS_ERRLIST && !defined(_SQUID_NETBSD_)
extern char *sys_errlist[];
#endif
-#include "autoconf.h"
+#if XMALLOC_STATISTICS
+#define DBG_MAXSIZE (1024*1024)
+#define DBG_GRAIN (16)
+#define DBG_MAXINDEX (DBG_MAXSIZE/DBG_GRAIN)
+#define DBG_INDEX(sz) (sz<DBG_MAXSIZE?(sz+DBG_GRAIN-1)/DBG_GRAIN:DBG_MAXINDEX)
+static int malloc_sizes[DBG_MAXINDEX + 1];
+static int dbg_stat_init = 0;
+
+static void stat_init()
+{
+ int i;
+ for (i = 0; i <= DBG_MAXINDEX; i++)
+ malloc_sizes[i] = 0;
+ dbg_stat_init = 1;
+}
+
+static int malloc_stat(sz)
+ int sz;
+{
+ if (!dbg_stat_init)
+ stat_init();
+ return malloc_sizes[DBG_INDEX(sz)] += 1;
+}
+
+void malloc_statistics(func, data)
+ void (*func) _PARAMS((int, int, void *));
+ void *data;
+{
+ int i;
+ for (i = 0; i <= DBG_MAXSIZE; i += DBG_GRAIN)
+ func(i, malloc_sizes[DBG_INDEX(i)], data);
+}
+#endif /* XMALLOC_STATISTICS */
+
#if XMALLOC_DEBUG
static void check_init()
{
for (B = 0; B < DBG_ARRY_SZ; B++) {
- for (I = 0; I < DBG_ARRY_SZ; I++) {
- malloc_ptrs[B][I] = NULL;
- malloc_size[B][I] = 0;
- }
+ for (I = 0; I < DBG_ARRY_SZ; I++) {
+ malloc_ptrs[B][I] = NULL;
+ malloc_size[B][I] = 0;
+ }
}
dbg_initd = 1;
}
}
#if XMALLOC_DEBUG
check_malloc(p, sz);
+#endif
+#if XMALLOC_STATISTICS
+ malloc_stat(sz);
#endif
return (p);
}
}
#if XMALLOC_DEBUG
check_malloc(p, sz);
+#endif
+#if XMALLOC_STATISTICS
+ malloc_stat(sz);
#endif
return (p);
}
}
#if XMALLOC_DEBUG
check_malloc(p, sz * n);
+#endif
+#if XMALLOC_STATISTICS
+ malloc_stat(sz);
#endif
return (p);
}
char *s;
{
static char *p = NULL;
- int sz;
+ size_t sz;
if (s == NULL) {
if (failure_notify) {
exit(1);
}
sz = strlen(s);
- p = (char *) xmalloc((size_t) sz + 1);
+ p = xmalloc((size_t) sz + 1);
memcpy(p, s, sz); /* copy string */
p[sz] = '\0'; /* terminate string */
return (p);
}
#endif
-#if !HAVE_STRERROR
-char *strerror(n)
-int n;
+void xmemcpy(from, to, len)
+ void *from;
+ void *to;
+ int len;
{
- return (xstrerror(n));
-}
+#if HAVE_MEMMOVE
+ (void) memmove(from, to, len);
+#elif HAVE_BCOPY
+ bcopy(to, from, len);
+#else
+ (void) memcpy(from, to, len);
#endif
+}
#!/bin/sh
#
-# $Id: RunAccel.in,v 1.3 1996/05/03 22:56:19 wessels Exp $
+# $Id: RunAccel.in,v 1.4 1996/07/09 03:41:15 wessels Exp $
# enable HTTP requests on port 80
port="-a 80"
prefix=@prefix@
exec_prefix=@exec_prefix@
-PATH=@bindir@:/bin
+logdir=@localstatedir@
+PATH=@bindir@:/bin:/usr/bin
export PATH
if test $# = 1 ; then
failcount=0
while : ; do
- echo "Running: squid $port -s $conf >> squid.out 2>&1"
+ echo "Running: squid $port -s $conf >> $logdir/squid.out 2>&1"
start=`date '+%d%H%M%S'`
- squid $port -s $conf >> squid.out 2>&1
+ squid $port -s $conf >> $logdir/squid.out 2>&1
stop=`date '+%d%H%M%S'`
t=`expr $stop - $start`
if test 0 -le $t -a $t -lt 5 ; then
#!/bin/sh
#
-# $Id: RunCache.in,v 1.5 1996/05/03 22:56:19 wessels Exp $
+# $Id: RunCache.in,v 1.6 1996/07/09 03:41:15 wessels Exp $
prefix=@prefix@
exec_prefix=@exec_prefix@
-PATH=@bindir@:/bin
+logdir=@localstatedir@
+PATH=@bindir@:/bin:/usr/bin
export PATH
conf=""
failcount=0
while : ; do
- echo "Running: squid -s $conf >> squid.out 2>&1"
+ echo "Running: squid -s $conf >> $logdir/squid.out 2>&1"
start=`date '+%d%H%M%S'`
- squid -s $conf >> squid.out 2>&1
+ squid -s $conf >> $logdir/squid.out 2>&1
stop=`date '+%d%H%M%S'`
t=`expr $stop - $start`
if test 0 -le $t -a $t -lt 5 ; then
# Version 1 did all this in memory, but the log file can be a
# little on the large side... 8-(
-# $Id: check_cache.pl,v 1.2 1996/05/01 22:36:22 wessels Exp $
+# $Id: check_cache.pl,v 1.3 1996/07/09 03:41:16 wessels Exp $
require "getopts.pl";
&Getopts("c:dl:rt:v");
$host=(shift || 'localhost') ;
$port=(shift || '3130') ;
-@CODES=('xxx', 'QUERY', 'HIT', 'MISS', 'ERROR');
+# just copy this from src/proto.c
+@CODES=(
+ "ICP_INVALID",
+ "ICP_QUERY",
+ "UDP_HIT",
+ "UDP_MISS",
+ "ICP_ERR",
+ "ICP_SEND",
+ "ICP_SENDA",
+ "ICP_DATABEG",
+ "ICP_DATA",
+ "ICP_DATAEND",
+ "ICP_SECHO",
+ "ICP_DECHO",
+ "ICP_OP_UNUSED0",
+ "ICP_OP_UNUSED1",
+ "ICP_OP_UNUSED2",
+ "ICP_OP_UNUSED3",
+ "ICP_OP_UNUSED4",
+ "ICP_OP_UNUSED5",
+ "ICP_OP_UNUSED6",
+ "ICP_OP_UNUSED7",
+ "ICP_OP_UNUSED8",
+ "ICP_OP_UNUSED9",
+ "UDP_DENIED",
+ "UDP_HIT_OBJ",
+ "ICP_END"
+);
require 'sys/socket.ph';
while (<>) {
chop;
- $request_template = 'CCnx4x8x4a4a' . length;
- $request = pack($request_template, 1, 1, 24 + length, $myip, $_);
+ $request_template = 'CCnx4Nx4x4a4a' . length;
+ $request = pack($request_template, 1, 1, 24 + length, ~0, $myip, $_);
die "send: $!\n" unless
send(SOCK, $request, 0, $them);
die "recv: $!\n" unless
- recv(SOCK, $reply, 1024, 0);
- ($type,$ver,$len,$payload) = unpack('CCnx4x8x4A', $reply);
- print $CODES[$type] . " $_\n";
+ $theiraddr = recv(SOCK, $reply, 1024, 0);
+ ($junk, $junk, $sourceaddr, $junk) = unpack($sockaddr, $theiraddr);
+ @theirip = unpack('C4', $sourceaddr);
+ ($type,$ver,$len,$payload) = unpack('CCnx4x8x4A', $reply);
+ print join('.', @theirip) . ' ' . $CODES[$type] . " $_\n";
}
#
# Makefile for the Squid Object Cache server
#
-# $Id: Makefile.in,v 1.25 1996/05/03 22:56:20 wessels Exp $
+# $Id: Makefile.in,v 1.26 1996/07/09 03:41:17 wessels Exp $
#
# Uncomment and customize the following to suit your needs:
#
LN_S = @LN_S@
PERL = @PERL@
CRYPT_LIB = @CRYPT_LIB@
-STD_CFLAGS = @STD_CFLAGS@
-STD_LDFLAGS = @STD_LDFLAGS@
-XTRA_CFLAGS = @XTRA_CFLAGS@
+AC_CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
XTRA_LIBS = @XTRA_LIBS@
XTRA_OBJS = @XTRA_OBJS@
+MV = @MV@
+RM = @RM@
SHELL = /bin/sh
INCLUDE = -I. -I../include -I$(srcdir)/../include
-CFLAGS = $(STD_CFLAGS) $(XTRA_CFLAGS) $(INCLUDE) $(DEFINES)
-LDFLAGS = $(STD_LDFLAGS)
-LIBS = -L../lib -lregex -lutil $(XTRA_LIBS)
-CLIENT_LIBS = -L../lib -lutil $(XTRA_LIBS)
+CFLAGS = $(AC_CFLAGS) $(INCLUDE) $(DEFINES)
+LIBS = -L../lib -lregex -lmiscutil $(XTRA_LIBS)
+CLIENT_LIBS = -L../lib -lmiscutil $(XTRA_LIBS)
PROGS = squid client
UTILS = dnsserver ftpget
s%@DEFAULT_SWAP_DIR@%$(DEFAULT_SWAP_DIR)%g" <$? >$@
install-mkdirs:
- @if test ! -d $(prefix); then \
+ -@if test ! -d $(prefix); then \
echo "mkdir $(prefix)"; \
mkdir $(prefix); \
fi
- @if test ! -d $(exec_prefix); then \
+ -@if test ! -d $(exec_prefix); then \
echo "mkdir $(exec_prefix)"; \
mkdir $(exec_prefix); \
fi
- @if test ! -d $(bindir); then \
+ -@if test ! -d $(bindir); then \
echo "mkdir $(bindir)"; \
mkdir $(bindir); \
fi
- @if test ! -d $(libexecdir); then \
+ -@if test ! -d $(libexecdir); then \
echo "mkdir $(libexecdir)"; \
mkdir $(libexecdir); \
fi
- @if test ! -d $(sysconfdir); then \
+ -@if test ! -d $(sysconfdir); then \
echo "mkdir $(sysconfdir)"; \
mkdir $(sysconfdir); \
fi
- @if test ! -d $(localstatedir); then \
+ -@if test ! -d $(localstatedir); then \
echo "mkdir $(localstatedir)"; \
mkdir $(localstatedir); \
fi
- @if test ! -d $(localstatedir)/logs; then \
+ -@if test ! -d $(localstatedir)/logs; then \
echo "mkdir $(localstatedir)/logs"; \
mkdir $(localstatedir)/logs; \
fi
install: all install-mkdirs
@for f in $(PROGS); do \
+ if test -f $(bindir)/$$f; then \
+ echo $(MV) $(bindir)/$$f $(bindir)/-$$f; \
+ $(MV) $(bindir)/$$f $(bindir)/-$$f; \
+ fi; \
echo $(INSTALL_BIN) $$f $(bindir); \
$(INSTALL_BIN) $$f $(bindir); \
+ if test -f $(bindir)/-$$f; then \
+ echo $(RM) -f $(bindir)/-$$f; \
+ $(RM) $(bindir)/-$$f; \
+ fi; \
done
@for f in $(UTILS); do \
+ if test -f $(libexecdir)/$$f; then \
+ echo $(MV) $(libexecdir)/$$f $(libexecdir)/-$$f; \
+ $(MV) $(libexecdir)/$$f $(libexecdir)/-$$f; \
+ fi; \
echo $(INSTALL_BIN) $$f $(libexecdir); \
$(INSTALL_BIN) $$f $(libexecdir); \
+ if test -f $(libexecdir)/-$$f; then \
+ echo $(RM) -f $(libexecdir)/-$$f; \
+ $(RM) $(libexecdir)/-$$f; \
+ fi; \
done
@for f in $(CGIPROGS); do \
+ if test -f $(libexecdir)/$$f; then \
+ echo $(MV) $(libexecdir)/$$f $(libexecdir)/-$$f; \
+ $(MV) $(libexecdir)/$$f $(libexecdir)/-$$f; \
+ fi; \
echo $(INSTALL_BIN) $$f $(libexecdir); \
$(INSTALL_BIN) $$f $(libexecdir); \
+ if test -f $(libexecdir)/-$$f; then \
+ echo $(RM) -f $(libexecdir)/-$$f; \
+ $(RM) $(libexecdir)/-$$f; \
+ fi; \
done
$(INSTALL_FILE) squid.conf $(sysconfdir)/squid.conf.default
@if test -f $(sysconfdir)/squid.conf ; then \
realclean: clean
-rm -f Makefile squid.conf squid.conf.pre
+
+tags:
+ ctags *.[ch] ../include/*.h ../lib/*.[ch]
-/* "$Id: acl.cc,v 1.14 1996/05/03 22:56:21 wessels Exp $" */
-
/*
- * DEBUG: Section 28 acl
+ * $Id: acl.cc,v 1.15 1996/07/09 03:41:17 wessels Exp $
+ *
+ * DEBUG: section 28 Access Control
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
*/
#include "squid.h"
static struct _acl *AclList = NULL;
static struct _acl **AclListTail = &AclList;
-static int aclMatchAcl _PARAMS((struct _acl *, struct in_addr, method_t, protocol_t, char *host, int port, char *request));
+static void aclDestroyAclList _PARAMS((struct _acl_list * list));
+static void aclDestroyIpList _PARAMS((struct _acl_ip_data * data));
+static void aclDestroyRegexList _PARAMS((struct _relist * data));
+static void aclDestroyTimeList _PARAMS((struct _acl_time_data * data));
static int aclMatchAclList _PARAMS((struct _acl_list *, struct in_addr, method_t, protocol_t, char *host, int port, char *request));
-
-static acl_t aclType(s)
+static int aclMatchInteger _PARAMS((intlist * data, int i));
+static int aclMatchIp _PARAMS((struct _acl_ip_data * data, struct in_addr c));
+static int aclMatchRegex _PARAMS((relist * data, char *word));
+static int aclMatchTime _PARAMS((struct _acl_time_data * data, time_t when));
+static int aclMatchEndOfWord _PARAMS((wordlist * data, char *word));
+static intlist *aclParseIntlist _PARAMS((void));
+static struct _acl_ip_data *aclParseIpList _PARAMS((void));
+static intlist *aclParseMethodList _PARAMS((void));
+static intlist *aclParseProtoList _PARAMS((void));
+static struct _relist *aclParseRegexList _PARAMS((void));
+static struct _acl_time_data *aclParseTimeSpec _PARAMS((void));
+static wordlist *aclParseWordList _PARAMS((void));
+static squid_acl aclType _PARAMS((char *s));
+
+static squid_acl aclType(s)
char *s;
{
if (!strcmp(s, "src"))
return ACL_SRC_IP;
+ if (!strcmp(s, "dst"))
+ return ACL_DST_IP;
if (!strcmp(s, "domain"))
return ACL_DST_DOMAIN;
if (!strcmp(s, "time"))
return ACL_URL_PORT;
if (!strcmp(s, "user"))
return ACL_USER;
- if (!strcmp(s, "proto"))
+ if (!strncmp(s, "proto", 5))
return ACL_PROTO;
if (!strcmp(s, "method"))
return ACL_METHOD;
}
-intlist *aclParseIntlist()
+static intlist *aclParseIntlist()
{
intlist *head = NULL;
intlist **Tail = &head;
intlist *q = NULL;
char *t = NULL;
while ((t = strtok(NULL, w_space))) {
- q = (intlist *) xcalloc(1, sizeof(intlist));
+ q = xcalloc(1, sizeof(intlist));
q->i = atoi(t);
*(Tail) = q;
Tail = &q->next;
return head;
}
-intlist *aclParseProtoList()
+static intlist *aclParseProtoList()
{
intlist *head = NULL;
intlist **Tail = &head;
intlist *q = NULL;
char *t = NULL;
while ((t = strtok(NULL, w_space))) {
- q = (intlist *) xcalloc(1, sizeof(intlist));
+ q = xcalloc(1, sizeof(intlist));
q->i = (int) urlParseProtocol(t);
*(Tail) = q;
Tail = &q->next;
return head;
}
-intlist *aclParseMethodList()
+static intlist *aclParseMethodList()
{
intlist *head = NULL;
intlist **Tail = &head;
intlist *q = NULL;
char *t = NULL;
while ((t = strtok(NULL, w_space))) {
- q = (intlist *) xcalloc(1, sizeof(intlist));
+ q = xcalloc(1, sizeof(intlist));
q->i = (int) urlParseMethod(t);
*(Tail) = q;
Tail = &q->next;
return head;
}
-struct _acl_ip_data *aclParseIpList()
+/* Decode a ascii representation (asc) of a IP adress, and place
+ * adress and netmask information in addr and mask.
+ */
+static int decode_addr(asc, addr, mask)
+ char *asc;
+ struct in_addr *addr, *mask;
{
- char *t = NULL;
+ struct hostent *hp = NULL;
+ u_num32 a;
+ int a1, a2, a3, a4;
+
+ switch (sscanf(asc, "%d.%d.%d.%d", &a1, &a2, &a3, &a4)) {
+ case 4: /* a dotted quad */
+ if ((a = inet_addr(asc)) != INADDR_NONE ||
+ !strcmp(asc, "255.255.255.255")) {
+ addr->s_addr = a;
+ /* inet_addr() outputs in network byte order */
+ }
+ break;
+ case 1: /* a significant bits value for a mask */
+ if (a1 >= 0 && a1 < 33) {
+ addr->s_addr = htonl(0xffffffff << (32 - a1));
+ break;
+ }
+ default:
+ if ((hp = gethostbyname(asc)) != NULL) {
+ /* We got a host name */
+ xmemcpy(addr, hp->h_addr, hp->h_length);
+ } else {
+ /* XXX: Here we could use getnetbyname */
+ debug(28, 0, "decode_addr: Invalid IP address or hostname '%s'\n", asc);
+ return 0; /* This is not valid address */
+ }
+ break;
+ }
+
+ if (mask != NULL) { /* mask == NULL if called to decode a netmask */
+
+ /* Guess netmask */
+ a = ntohl(addr->s_addr);
+ if (!(a & 0xFFFFFFFF))
+ mask->s_addr = htonl(0x00000000);
+ else if (!(a & 0x00FFFFFF))
+ mask->s_addr = htonl(0xFF000000);
+ else if (!(a & 0x0000FFFF))
+ mask->s_addr = htonl(0xFFFF0000);
+ else if (!(a & 0x000000FF))
+ mask->s_addr = htonl(0xFFFFFF00);
+ else
+ mask->s_addr = htonl(0xFFFFFFFF);
+ }
+ return 1;
+}
+
+
+static struct _acl_ip_data *aclParseIpList()
+{
+ char *t = NULL, *p = NULL;
struct _acl_ip_data *head = NULL;
struct _acl_ip_data **Tail = &head;
struct _acl_ip_data *q = NULL;
- int a1, a2, a3, a4;
- int m1, m2, m3, m4;
- struct in_addr lmask;
- int c;
+ static char addr1[256], addr2[256], mask[256];
while ((t = strtok(NULL, w_space))) {
- q = (struct _acl_ip_data *) xcalloc(1, sizeof(struct _acl_ip_data));
- a1 = a2 = a3 = a4 = 0;
+ q = xcalloc(1, sizeof(struct _acl_ip_data));
if (!strcasecmp(t, "all")) {
- lmask.s_addr = 0;
+ q->addr1.s_addr = 0;
+ q->addr2.s_addr = 0;
+ q->mask.s_addr = 0;
} else {
- c = sscanf(t, "%d.%d.%d.%d/%d.%d.%d.%d",
- &a1, &a2, &a3, &a4,
- &m1, &m2, &m3, &m4);
- switch (c) {
- case 4:
- if (a1 == 0 && a2 == 0 && a3 == 0 && a4 == 0) /* world */
- lmask.s_addr = 0x00000000;
- else if (a2 == 0 && a3 == 0 && a4 == 0) /* class A */
- lmask.s_addr = htonl(0xff000000);
- else if (a3 == 0 && a4 == 0) /* class B */
- lmask.s_addr = htonl(0xffff0000);
- else if (a4 == 0) /* class C */
- lmask.s_addr = htonl(0xffffff00);
- else
- lmask.s_addr = 0xffffffff;
- break;
- case 5:
- if (m1 < 0 || m1 > 32) {
- debug(28, 0, "%s line %d: %s\n",
- cfg_filename, config_lineno, config_input_line);
- debug(28, 0, "aclParseIpList: Ignoring invalid IP acl entry '%s'\n", t);
- safe_free(q);
- continue;
- }
- lmask.s_addr = htonl(0xffffffff << (32 - m1));
- break;
- case 8:
- lmask.s_addr = htonl(m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4);
- break;
- default:
+ p = t;
+ memset(addr1, 0, sizeof(addr1));
+ memset(addr2, 0, sizeof(addr2));
+ memset(mask, 0, sizeof(mask));
+
+ /* Split the adress in addr1-addr2/mask */
+ strncpy(addr1, p, strcspn(t, "-/"));
+ p += strcspn(t, "-/");
+ if (*p == '-') {
+ p++;
+ strncpy(addr2, p, strcspn(t, "/"));
+ p += strcspn(p, "/");
+ }
+ if (*p == '/') {
+ p++;
+ strcpy(mask, p);
+ }
+ /* Decode addr1 */
+ if (!decode_addr(addr1, &q->addr1, &q->mask)) {
debug(28, 0, "%s line %d: %s\n",
cfg_filename, config_lineno, config_input_line);
- debug(28, 0, "aclParseIpList: Ignoring invalid IP acl entry '%s'\n", t);
+ debug(28, 0, "aclParseIpList: Ignoring invalid IP acl entry: unknown first address '%s'\n", addr1);
+ safe_free(q);
+ continue;
+ }
+ /* Decode addr2 */
+ if (*addr2 && !decode_addr(addr2, &q->addr2, &q->mask)) {
+ debug(28, 0, "%s line %d: %s\n",
+ cfg_filename, config_lineno, config_input_line);
+ debug(28, 0, "aclParseIpList: Ignoring invalid IP acl entry: unknown second address '%s'\n", addr1);
+ safe_free(q);
+ continue;
+ }
+ /* Decode mask */
+ if (*mask && !decode_addr(mask, &q->mask, NULL)) {
+ debug(28, 0, "%s line %d: %s\n",
+ cfg_filename, config_lineno, config_input_line);
+ debug(28, 0, "aclParseIpList: Ignoring invalid IP acl entry: unknown netmask '%s'\n", mask);
safe_free(q);
continue;
}
}
- q->addr1.s_addr = htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
- q->mask1.s_addr = lmask.s_addr;
*(Tail) = q;
Tail = &q->next;
}
return head;
}
-struct _acl_time_data *aclParseTimeSpec()
+static struct _acl_time_data *aclParseTimeSpec()
{
struct _acl_time_data *data = NULL;
int h1, m1, h2, m2;
char *t = NULL;
- data = (struct _acl_time_data *) xcalloc(1, sizeof(struct _acl_time_data));
+ data = xcalloc(1, sizeof(struct _acl_time_data));
while ((t = strtok(NULL, w_space))) {
if (*t < '0' || *t > '9') {
/* assume its day-of-week spec */
case 'A':
data->weekbits |= ACL_SATURDAY;
break;
+ case 'D':
+ data->weekbits |= ACL_WEEKDAYS;
+ break;
default:
debug(28, 0, "%s line %d: %s\n",
cfg_filename, config_lineno, config_input_line);
return data;
}
-struct _relist *aclParseRegexList()
+static struct _relist *aclParseRegexList()
{
relist *head = NULL;
relist **Tail = &head;
debug(28, 0, "aclParseRegexList: Invalid regular expression: '%s'\n", t);
continue;
}
- q = (relist *) xcalloc(1, sizeof(relist));
+ q = xcalloc(1, sizeof(relist));
q->pattern = xstrdup(t);
q->regex = comp;
*(Tail) = q;
return head;
}
-wordlist *aclParseWordList()
+static wordlist *aclParseWordList()
{
wordlist *head = NULL;
wordlist **Tail = &head;
wordlist *q = NULL;
char *t = NULL;
while ((t = strtok(NULL, w_space))) {
- q = (wordlist *) xcalloc(1, sizeof(wordlist));
+ q = xcalloc(1, sizeof(wordlist));
q->key = xstrdup(t);
*(Tail) = q;
Tail = &q->next;
char *t = NULL;
struct _acl *A = NULL;
- A = (struct _acl *) xcalloc(1, sizeof(struct _acl));
+ A = xcalloc(1, sizeof(struct _acl));
/* snarf the ACL name */
if ((t = strtok(NULL, w_space)) == NULL) {
debug(28, 0, "%s line %d: %s\n",
}
switch (A->type = aclType(t)) {
case ACL_SRC_IP:
+ case ACL_DST_IP:
A->data = (void *) aclParseIpList();
break;
case ACL_DST_DOMAIN:
xfree(A);
return;
/* NOTREACHED */
- break;
}
A->cfgline = xstrdup(config_input_line);
*AclListTail = A;
debug(28, 0, "aclParseAccessLine: missing 'allow' or 'deny'.\n");
return;
}
- A = (struct _acl_access *) xcalloc(1, sizeof(struct _acl_access));
+ A = xcalloc(1, sizeof(struct _acl_access));
if (!strcmp(t, "allow"))
A->allow = 1;
else if (!strcmp(t, "deny"))
* by '!' for negation */
Tail = &A->acl_list;
while ((t = strtok(NULL, w_space))) {
- L = (struct _acl_list *) xcalloc(1, sizeof(struct _acl_list));
+ L = xcalloc(1, sizeof(struct _acl_list));
L->op = 1; /* defaults to non-negated */
if (*t == '!') {
/* negated ACL */
*T = A;
}
-int aclMatchIp(data, c)
+static int aclMatchIp(data, c)
struct _acl_ip_data *data;
struct in_addr c;
{
struct in_addr h;
+ unsigned long lh, la1, la2;
+
while (data) {
- h.s_addr = c.s_addr & data->mask1.s_addr;
+ h.s_addr = c.s_addr & data->mask.s_addr;
debug(28, 3, "aclMatchIp: h = %s\n", inet_ntoa(h));
debug(28, 3, "aclMatchIp: addr1 = %s\n", inet_ntoa(data->addr1));
- if (h.s_addr == data->addr1.s_addr) {
- debug(28, 3, "aclMatchIp: returning 1\n");
- return 1;
+ debug(28, 3, "aclMatchIp: addr2 = %s\n", inet_ntoa(data->addr2));
+ if (!data->addr2.s_addr) {
+ if (h.s_addr == data->addr1.s_addr) {
+ debug(28, 3, "aclMatchIp: returning 1\n");
+ return 1;
+ }
+ } else {
+ /* This is a range check */
+ lh = ntohl(h.s_addr);
+ la1 = ntohl(data->addr1.s_addr);
+ la2 = ntohl(data->addr2.s_addr);
+ if (lh >= la1 && lh <= la2) {
+ debug(28, 3, "aclMatchIp: returning 1\n");
+ return 1;
+ }
}
data = data->next;
}
return 0;
}
-int aclMatchWord(data, word)
+#ifdef UNUSED_CODE
+static int aclMatchWord(data, word)
wordlist *data;
char *word;
{
}
return 0;
}
-int aclMatchRegex(data, word)
+#endif
+
+static int aclMatchEndOfWord(data, word)
+ wordlist *data;
+ char *word;
+{
+ int offset;
+ if (word == NULL)
+ return 0;
+ debug(28, 3, "aclMatchEndOfWord: checking '%s'\n", word);
+ for (; data; data = data->next) {
+ debug(28, 3, "aclMatchEndOfWord: looking for '%s'\n", data->key);
+ if ((offset = strlen(word) - strlen(data->key)) < 0)
+ continue;
+ if (strcmp(word + offset, data->key) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+static int aclMatchRegex(data, word)
relist *data;
char *word;
{
}
return 0;
}
-int aclMatchInteger(data, i)
+
+static int aclMatchInteger(data, i)
intlist *data;
int i;
{
return 0;
}
-int aclMatchTime(data, when)
+static int aclMatchTime(data, when)
struct _acl_time_data *data;
time_t when;
{
if (when != last_when) {
last_when = when;
- memcpy(&tm, localtime(&when), sizeof(struct tm));
+ xmemcpy(&tm, localtime(&when), sizeof(struct tm));
}
debug(28, 3, "aclMatchTime: checking %d-%d, weekbits=%x\n",
data->start, data->stop, data->weekbits);
return data->weekbits & (1 << tm.tm_wday) ? 1 : 0;
}
-static int aclMatchAcl(acl, c, m, pr, h, po, r)
+int aclMatchAcl(acl, c, m, pr, h, po, r)
struct _acl *acl;
struct in_addr c;
method_t m;
int po;
char *r;
{
+ struct hostent *hp = NULL;
+ struct in_addr dst;
+ int k;
if (!acl)
return 0;
debug(28, 3, "aclMatchAcl: checking '%s'\n", acl->cfgline);
case ACL_SRC_IP:
return aclMatchIp(acl->data, c);
/* NOTREACHED */
- break;
+ case ACL_DST_IP:
+ if ((hp = ipcache_gethostbyname(h, IP_LOOKUP_IF_MISS)) == NULL) {
+ debug(28, 3, "aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n",
+ acl->name, h);
+ return 0; /* cant check, return no match */
+ }
+ for (k = 0; hp->h_addr_list[k]; k++) {
+ xmemcpy(&dst.s_addr, hp->h_addr_list[k], hp->h_length);
+ if (aclMatchIp(acl->data, dst))
+ return 1;
+ }
+ return 0;
+ /* NOTREACHED */
case ACL_DST_DOMAIN:
- return aclMatchWord(acl->data, h);
+ /* XXX This probably needs to use matchDomainName() */
+ return aclMatchEndOfWord(acl->data, h);
/* NOTREACHED */
- break;
case ACL_TIME:
return aclMatchTime(acl->data, squid_curtime);
/* NOTREACHED */
- break;
case ACL_URL_REGEX:
return aclMatchRegex(acl->data, r);
/* NOTREACHED */
- break;
case ACL_URL_PORT:
return aclMatchInteger(acl->data, po);
/* NOTREACHED */
- break;
case ACL_USER:
debug(28, 0, "aclMatchAcl: ACL_USER unimplemented\n");
return 0;
/* NOTREACHED */
- break;
case ACL_PROTO:
return aclMatchInteger(acl->data, pr);
/* NOTREACHED */
- break;
case ACL_METHOD:
return aclMatchInteger(acl->data, m);
/* NOTREACHED */
- break;
case ACL_NONE:
default:
debug(28, 0, "aclMatchAcl: '%s' has bad type %d\n",
acl->name, acl->type);
return 0;
}
- fatal_dump("aclMatchAcl: This should never happen.");
- return 0;
+ /* NOTREACHED */
}
static int aclMatchAclList(list, c, m, pr, h, po, r)
debug(28, 3, "aclDestroyAcls: '%s'\n", a->cfgline);
switch (a->type) {
case ACL_SRC_IP:
+ case ACL_DST_IP:
aclDestroyIpList(a->data);
break;
case ACL_DST_DOMAIN:
-/* $Id: cache_cf.cc,v 1.55 1996/05/03 22:56:21 wessels Exp $ */
+/*
+ * $Id: cache_cf.cc,v 1.56 1996/07/09 03:41:19 wessels Exp $
+ *
+ * DEBUG: section 3 Configuration File Parsing
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
-/* DEBUG: Section 3 cache_cf: Configuration file parsing */
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include "squid.h"
int maxObjSize;
int defaultTtl;
char *relayHost;
- int relayPort;
+ u_short relayPort;
} Wais;
int negativeTtl;
int negativeDnsTtl;
int maxRequestSize;
double hotVmFactor;
struct {
- int ascii;
- int udp;
+ u_short http;
+ u_short icp;
} Port;
struct {
char *log;
struct {
char *host;
char *prefix;
- int port;
+ u_short port;
int withProxy;
} Accel;
char *appendDomain;
char *ftpUser;
struct {
char *host;
- int port;
+ u_short port;
char *file;
int rate;
} Announce;
+ struct {
+ struct in_addr tcp_incoming;
+ struct in_addr tcp_outgoing;
+ struct in_addr udp_incoming;
+ struct in_addr udp_outgoing;
+ } Addrs;
wordlist *cache_dirs;
wordlist *http_stoplist;
wordlist *gopher_stoplist;
wordlist *ftp_stoplist;
- wordlist *bind_addr_list;
+ wordlist *hierarchy_stoplist;
wordlist *local_domain_list;
wordlist *inside_firewall_list;
wordlist *dns_testname_list;
#define DefaultSwapHighWaterMark 90 /* 90% */
#define DefaultSwapLowWaterMark 75 /* 75% */
-#define DefaultFtpDefaultTtl (7 * 24 * 60 * 60) /* 1 week */
+#define DefaultFtpDefaultTtl (3 * 24 * 60 * 60) /* 3 days */
#define DefaultFtpMaxObjSize (4 << 20) /* 4 MB */
-#define DefaultGopherDefaultTtl (7 * 24 * 60 * 60) /* 1 week */
+#define DefaultGopherDefaultTtl (3 * 24 * 60 * 60) /* 3 days */
#define DefaultGopherMaxObjSize (4 << 20) /* 4 MB */
-#define DefaultHttpDefaultTtl (7 * 24 * 60 * 60) /* 1 week */
+#define DefaultHttpDefaultTtl (3 * 24 * 60 * 60) /* 3 days */
#define DefaultHttpMaxObjSize (4 << 20) /* 4 MB */
-#define DefaultWaisDefaultTtl (7 * 24 * 60 * 60) /* 1 week */
+#define DefaultWaisDefaultTtl (3 * 24 * 60 * 60) /* 3 days */
#define DefaultWaisMaxObjSize (4 << 20) /* 4 MB */
#define DefaultWaisRelayHost (char *)NULL
-#define DefaultWaisRelayPort -1
+#define DefaultWaisRelayPort 0
#define DefaultNegativeTtl (5 * 60) /* 5 min */
#define DefaultNegativeDnsTtl (2 * 60) /* 2 min */
#define DefaultDefaultAgeMax (3600 * 24 * 30) /* 30 days */
#define DefaultCleanRate -1 /* disabled */
#define DefaultDnsChildren 5 /* 3 processes */
-#define DefaultDnsChildrenMax 32 /* 32 processes */
#define DefaultMaxRequestSize (100 << 10) /* 100Kb */
#define DefaultHotVmFactor 0.0 /* disabled */
-#define DefaultAsciiPortNum CACHE_HTTP_PORT
-#define DefaultUdpPortNum CACHE_ICP_PORT
+#define DefaultHttpPortNum CACHE_HTTP_PORT
+#define DefaultIcpPortNum CACHE_ICP_PORT
#define DefaultCacheLogFile DEFAULT_CACHE_LOG
#define DefaultAccessLogFile DEFAULT_ACCESS_LOG
#define DefaultAnnounceHost "sd.cache.nlanr.net"
#define DefaultAnnouncePort 3131
#define DefaultAnnounceFile (char *)NULL /* default NONE */
-#define DefaultAnnounceRate 86400 /* every 24 hours */
+#define DefaultAnnounceRate 0 /* Default off */
+#define DefaultTcpIncomingAddr INADDR_ANY
+#define DefaultTcpOutgoingAddr INADDR_NONE
+#define DefaultUdpIncomingAddr INADDR_ANY
+#define DefaultUdpOutgoingAddr INADDR_NONE
ip_acl *local_ip_list = NULL;
+ip_acl *firewall_ip_list = NULL;
int zap_disk_store = 0; /* off, try to rebuild from disk */
int httpd_accel_mode = 0; /* for fast access */
char *DefaultConfigFile = DEFAULT_CONFIG_FILE;
char *ConfigFile = NULL; /* the whole thing */
char *cfg_filename = NULL; /* just the last part */
+char ForwardedBy[256];
char w_space[] = " \t\n";
char config_input_line[BUFSIZ];
static void configSetFactoryDefaults _PARAMS((void));
static void configFreeMemory _PARAMS((void));
static void configDoConfigure _PARAMS((void));
+static char *safe_xstrdup _PARAMS((char *p));
static char fatal_str[BUFSIZ];
void self_destruct()
}
if (!(*list)) {
/* empty list */
- *list = (ip_acl *) xcalloc(1, sizeof(ip_acl));
+ *list = xcalloc(1, sizeof(ip_acl));
(*list)->next = NULL;
q = *list;
} else {
p = *list;
while (p->next)
p = p->next;
- q = (ip_acl *) xcalloc(1, sizeof(ip_acl));
+ q = xcalloc(1, sizeof(ip_acl));
q->next = NULL;
p->next = q;
}
if (!(*list)) {
/* empty list */
- *list = (wordlist *) xcalloc(1, sizeof(wordlist));
+ *list = xcalloc(1, sizeof(wordlist));
(*list)->key = xstrdup(key);
(*list)->next = NULL;
} else {
p = *list;
while (p->next)
p = p->next;
- q = (wordlist *) xcalloc(1, sizeof(wordlist));
+ q = xcalloc(1, sizeof(wordlist));
q->key = xstrdup(key);
q->next = NULL;
p->next = q;
#define GetInteger(var) \
token = strtok(NULL, w_space); \
- if( token == (char *) NULL) \
+ if( token == NULL) \
self_destruct(); \
if (sscanf(token, "%d", &var) != 1) \
self_destruct();
char *type = NULL;
char *hostname = NULL;
char *token = NULL;
- int ascii_port = CACHE_HTTP_PORT;
- int udp_port = CACHE_ICP_PORT;
- int proxy_only = 0;
+ u_short http_port = CACHE_HTTP_PORT;
+ u_short icp_port = CACHE_ICP_PORT;
+ int options = 0;
int weight = 1;
+ int i;
/* Parse a cache_host line */
if (!(hostname = strtok(NULL, w_space)))
if (!(type = strtok(NULL, w_space)))
self_destruct();
- GetInteger(ascii_port);
- GetInteger(udp_port);
+ GetInteger(i);
+ http_port = (u_short) i;
+ GetInteger(i);
+ icp_port = (u_short) i;
while ((token = strtok(NULL, w_space))) {
if (!strcasecmp(token, "proxy-only")) {
- proxy_only = 1;
+ options |= NEIGHBOR_PROXY_ONLY;
+ } else if (!strcasecmp(token, "no-query")) {
+ options |= NEIGHBOR_NO_QUERY;
} else if (!strncasecmp(token, "weight=", 7)) {
weight = atoi(token + 7);
} else {
}
if (weight < 1)
weight = 1;
- neighbors_cf_add(hostname, type, ascii_port, udp_port, proxy_only, weight);
+ neighbors_cf_add(hostname, type, http_port, icp_port, options, weight);
}
static void parseHostDomainLine()
{
char *host = NULL;
char *domain = NULL;
+ if (!(host = strtok(NULL, w_space)))
+ self_destruct();
+ while ((domain = strtok(NULL, ", \t\n")))
+ neighbors_cf_domain(host, domain);
+}
+static void parseHostAclLine()
+{
+ char *host = NULL;
+ char *aclname = NULL;
if (!(host = strtok(NULL, w_space)))
self_destruct();
- while ((domain = strtok(NULL, ", \t\n"))) {
- if (neighbors_cf_domain(host, domain) == 0)
- self_destruct();
- }
+ while ((aclname = strtok(NULL, ", \t\n")))
+ neighbors_cf_acl(host, aclname);
}
char *srcping;
srcping = strtok(NULL, w_space);
- if (srcping == (char *) NULL)
+ if (srcping == NULL)
self_destruct();
/* set source_ping, default is off. */
char *abort;
abort = strtok(NULL, w_space);
- if (abort == (char *) NULL)
+ if (abort == NULL)
self_destruct();
if (!strcasecmp(abort, "on") || !strcasecmp(abort, "quick"))
double d;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
if (sscanf(token, "%lf", &d) != 1)
self_destruct();
int i;
token = strtok(NULL, w_space); /* token: regex pattern */
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
pattern = xstrdup(token);
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.adminEmail);
Config.adminEmail = xstrdup(token);
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
wordlistAdd(&Config.cache_dirs, token);
}
static void parseHttpdAccelLine()
{
char *token;
- char buf[1024];
+ static char buf[BUFSIZ];
int i;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Accel.host);
Config.Accel.host = xstrdup(token);
char *proxy;
proxy = strtok(NULL, w_space);
- if (proxy == (char *) NULL)
+ if (proxy == NULL)
self_destruct();
/* set httpd_accel_with_proxy, default is off. */
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.effectiveUser);
safe_free(Config.effectiveGroup);
Config.effectiveUser = xstrdup(token);
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
return; /* group is optional */
Config.effectiveGroup = xstrdup(token);
}
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Log.log);
Config.Log.log = xstrdup(token);
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Log.access);
Config.Log.access = xstrdup(token);
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Log.hierarchy);
Config.Log.hierarchy = xstrdup(token);
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Log.store);
Config.Log.store = xstrdup(token);
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Program.ftpget);
Config.Program.ftpget = xstrdup(token);
{
char *token;
token = strtok(NULL, ""); /* Note "", don't separate these */
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Program.ftpget_opts);
Config.Program.ftpget_opts = xstrdup(token);
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Program.dnsserver);
Config.Program.dnsserver = xstrdup(token);
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
if (!strcasecmp(token, "on") || !strcasecmp(token, "enable"))
Config.commonLogFormat = 1;
char *token;
int i;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Wais.relayHost);
Config.Wais.relayHost = xstrdup(token);
GetInteger(i);
- Config.Wais.relayPort = i;
+ Config.Wais.relayPort = (u_short) i;
GetInteger(i);
Config.Wais.maxObjSize = i << 20;
}
-static void parseLocalIPLine()
+static void parseIPLine(list)
+ ip_acl **list;
{
char *token;
while ((token = strtok(NULL, w_space))) {
- addToIPACL(&local_ip_list, token, IP_DENY);
+ addToIPACL(list, token, IP_DENY);
}
}
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
return;
wordlistAdd(&Config.http_stoplist, token);
}
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
return;
wordlistAdd(&Config.gopher_stoplist, token);
}
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
return;
wordlistAdd(&Config.ftp_stoplist, token);
}
+static void parseHierarchyStoplistLine()
+{
+ char *token;
+ while ((token = strtok(NULL, w_space)))
+ wordlistAdd(&Config.hierarchy_stoplist, token);
+}
static void parseAppendDomainLine()
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
if (*token != '.')
self_destruct();
Config.appendDomain = xstrdup(token);
}
-static void parseBindAddressLine()
+static void parseAddressLine(addr)
+ struct in_addr *addr;
{
char *token;
+ struct hostent *hp = NULL;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
+ self_destruct();
+ if (inet_addr(token) != INADDR_NONE)
+ (*addr).s_addr = inet_addr(token);
+ else if ((hp = gethostbyname(token)))
+ xmemcpy(addr, hp->h_addr, hp->h_length);
+ else
self_destruct();
- debug(3, 1, "parseBindAddressLine: adding %s\n", token);
- wordlistAdd(&Config.bind_addr_list, token);
}
static void parseLocalDomainFile(fname)
char *fname;
{
- char tmp_line[BUFSIZ];
+ static char tmp_line[BUFSIZ];
FILE *fp = NULL;
char *t = NULL;
}
}
-static void parseAsciiPortLine()
+static void parseHttpPortLine()
{
char *token;
int i;
GetInteger(i);
- Config.Port.ascii = i;
+ if (i < 0)
+ i = 0;
+ Config.Port.http = (u_short) i;
}
-static void parseUdpPortLine()
+static void parseIcpPortLine()
{
char *token;
int i;
GetInteger(i);
- Config.Port.udp = i;
+ if (i < 0)
+ i = 0;
+ Config.Port.icp = (u_short) i;
}
static void parseNeighborTimeout()
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
if (!strcasecmp(token, "on"))
Config.singleParentBypass = 1;
char *token;
token = strtok(NULL, ""); /* Note "", don't separate these */
safe_free(Config.debugOptions);
- if (token == (char *) NULL) {
+ if (token == NULL) {
Config.debugOptions = NULL;
return;
}
char *token;
token = strtok(NULL, w_space);
safe_free(Config.pidFilename);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
Config.pidFilename = xstrdup(token);
}
char *token;
token = strtok(NULL, w_space);
safe_free(Config.visibleHostname);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
Config.visibleHostname = xstrdup(token);
}
{
char *token;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.ftpUser);
Config.ftpUser = xstrdup(token);
char *token;
int i;
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
self_destruct();
safe_free(Config.Announce.host);
Config.Announce.host = xstrdup(token);
Config.Announce.port = i;
}
token = strtok(NULL, w_space);
- if (token == (char *) NULL)
+ if (token == NULL)
return;
safe_free(Config.Announce.file);
Config.Announce.file = xstrdup(token);
/* Parse a cache_host_domain line */
else if (!strcmp(token, "cache_host_domain"))
parseHostDomainLine();
+ else if (!strcmp(token, "cache_host_acl"))
+ parseHostAclLine();
/* Parse a neighbor_timeout line */
else if (!strcmp(token, "neighbor_timeout"))
else if (!strcmp(token, "ftp_stop"))
parseFtpStopLine();
+ /* Parse a hierarchy_stoplist line */
+ else if (!strcmp(token, "hierarchy_stoplist"))
+ parseHierarchyStoplistLine();
+
/* Parse a gopher protocol line */
- /* XXX: Must go after any gopher* token */
else if (!strcmp(token, "gopher"))
parseGopherLine();
/* Parse a http protocol line */
- /* XXX: Must go after any http* token */
else if (!strcmp(token, "http"))
parseHttpLine();
/* Parse a ftp protocol line */
- /* XXX: Must go after any ftp* token */
else if (!strcmp(token, "ftp"))
parseFtpLine();
else if (!strcmp(token, "wais_relay"))
parseWAISRelayLine();
- /* Parse a local_ip line */
else if (!strcmp(token, "local_ip"))
- parseLocalIPLine();
+ parseIPLine(&local_ip_list);
+
+ else if (!strcmp(token, "firewall_ip"))
+ parseIPLine(&firewall_ip_list);
/* Parse a local_domain line */
else if (!strcmp(token, "local_domain"))
parseLocalDomainLine();
- /* Parse a bind_address line */
+ else if (!strcmp(token, "tcp_incoming_address"))
+ parseAddressLine(&Config.Addrs.tcp_incoming);
+
+ else if (!strcmp(token, "tcp_outgoing_address"))
+ parseAddressLine(&Config.Addrs.tcp_outgoing);
+
+ else if (!strcmp(token, "udp_incoming_address"))
+ parseAddressLine(&Config.Addrs.udp_incoming);
+
+ else if (!strcmp(token, "udp_outgoing_address"))
+ parseAddressLine(&Config.Addrs.udp_outgoing);
+
else if (!strcmp(token, "bind_address"))
- parseBindAddressLine();
+ parseAddressLine(&Config.Addrs.tcp_incoming);
+
+ else if (!strcmp(token, "outbound_address"))
+ parseAddressLine(&Config.Addrs.tcp_outgoing);
- /* Parse a ascii_port line */
- else if (!strcmp(token, "ascii_port"))
- parseAsciiPortLine();
+ /* Parse a http_port line */
+ else if (!strcmp(token, "http_port") || !strcmp(token, "ascii_port"))
+ parseHttpPortLine();
- /* Parse a udp_port line */
- else if (!strcmp(token, "udp_port"))
- parseUdpPortLine();
+ /* Parse a icp_port line */
+ else if (!strcmp(token, "icp_port") || !strcmp(token, "udp_port"))
+ parseIcpPortLine();
else if (!strcmp(token, "inside_firewall"))
parseInsideFirewallLine();
}
}
- /* Add INADDR_ANY to end of bind_addr_list as last chance */
- wordlistAdd(&Config.bind_addr_list, "0.0.0.0");
-
/* Sanity checks */
if (getClientLifetime() < getReadTimeout()) {
printf("WARNING: client_lifetime (%d seconds) is less than read_timeout (%d seconds).\n",
{
return Config.Wais.relayHost;
}
-int getWaisRelayPort()
+u_short getWaisRelayPort()
{
return Config.Wais.relayPort;
}
{
return Config.Accel.prefix;
}
+u_short getAccelPort()
+{
+ return Config.Accel.port;
+}
int getAccelWithProxy()
{
return Config.Accel.withProxy;
{
return Config.Log.log;
}
-int getAsciiPortNum()
+u_short getHttpPortNum()
{
- return Config.Port.ascii;
+ return Config.Port.http;
}
-int getUdpPortNum()
+u_short getIcpPortNum()
{
- return Config.Port.udp;
+ return Config.Port.icp;
}
char *getDnsProgram()
{
{
return Config.Announce.host;
}
-int getAnnouncePort()
+u_short getAnnouncePort()
{
return Config.Announce.port;
}
{
return Config.ftp_stoplist;
}
+wordlist *getHierarchyStoplist()
+{
+ return Config.hierarchy_stoplist;
+}
wordlist *getGopherStoplist()
{
return Config.gopher_stoplist;
{
return Config.dns_testname_list;
}
-wordlist *getBindAddrList()
+struct in_addr getTcpIncomingAddr()
{
- return Config.bind_addr_list;
+ return Config.Addrs.tcp_incoming;
}
-
-int setAsciiPortNum(p)
- int p;
+struct in_addr getTcpOutgoingAddr()
{
- return (Config.Port.ascii = p);
+ return Config.Addrs.tcp_outgoing;
}
-int setUdpPortNum(p)
- int p;
+struct in_addr getUdpIncomingAddr()
{
- return (Config.Port.udp = p);
+ return Config.Addrs.udp_incoming;
+}
+struct in_addr getUdpOutgoingAddr()
+{
+ return Config.Addrs.udp_outgoing;
}
-
-char *safe_xstrdup(p)
- char *p;
+u_short setHttpPortNum(port)
+ u_short port;
{
- return p ? xstrdup(p) : p;
+ return (Config.Port.http = port);
}
+u_short setIcpPortNum(port)
+ u_short port;
+{
+ return (Config.Port.icp = port);
+}
+
-int safe_strlen(p)
+static char *safe_xstrdup(p)
char *p;
{
- return p ? strlen(p) : -1;
+ return p ? xstrdup(p) : p;
}
static void configFreeMemory()
wordlistDestroy(&Config.http_stoplist);
wordlistDestroy(&Config.gopher_stoplist);
wordlistDestroy(&Config.ftp_stoplist);
- wordlistDestroy(&Config.bind_addr_list);
+ wordlistDestroy(&Config.hierarchy_stoplist);
wordlistDestroy(&Config.local_domain_list);
wordlistDestroy(&Config.inside_firewall_list);
wordlistDestroy(&Config.dns_testname_list);
Config.effectiveGroup = safe_xstrdup(DefaultEffectiveGroup);
Config.appendDomain = safe_xstrdup(DefaultAppendDomain);
- Config.Port.ascii = DefaultAsciiPortNum;
- Config.Port.udp = DefaultUdpPortNum;
+ Config.Port.http = DefaultHttpPortNum;
+ Config.Port.icp = DefaultIcpPortNum;
Config.Log.log = safe_xstrdup(DefaultCacheLogFile);
Config.Log.access = safe_xstrdup(DefaultAccessLogFile);
Config.Log.hierarchy = safe_xstrdup(DefaultHierarchyLogFile);
Config.Announce.port = DefaultAnnouncePort;
Config.Announce.file = safe_xstrdup(DefaultAnnounceFile);
Config.Announce.rate = DefaultAnnounceRate;
+ Config.Addrs.tcp_outgoing.s_addr = DefaultTcpOutgoingAddr;
+ Config.Addrs.tcp_incoming.s_addr = DefaultTcpIncomingAddr;
+ Config.Addrs.udp_outgoing.s_addr = DefaultUdpOutgoingAddr;
+ Config.Addrs.udp_incoming.s_addr = DefaultUdpIncomingAddr;
}
static void configDoConfigure()
neighbor_timeout = (time_t) Config.neighborTimeout;
single_parent_bypass = Config.singleParentBypass;
DnsPositiveTtl = Config.positiveDnsTtl;
+ sprintf(ForwardedBy, "Forwarded: by http://%s:%d/",
+ getMyHostname(), getHttpPortNum());
+
#if !ALLOW_HOT_CACHE
if (!httpd_accel_mode || Config.Accel.withProxy) {
-/* $Id: cachemgr.cc,v 1.9 1996/05/03 22:56:22 wessels Exp $ */
+/*
+ * $Id: cachemgr.cc,v 1.10 1996/07/09 03:41:19 wessels Exp $
+ *
+ * DEBUG: Section 0 CGI Cache Manager
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include "config.h"
-#include "autoconf.h"
-#include "version.h"
+#if HAVE_UNISTD_H
#include <unistd.h>
+#endif
+#if HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#if HAVE_STDIO_H
#include <stdio.h>
+#endif
+#if HAVE_SYS_TYPES_H
#include <sys/types.h>
+#endif
+#if HAVE_CTYPE_H
#include <ctype.h>
+#endif
+#if HAVE_ERRNO_H
#include <errno.h>
+#endif
+#if HAVE_FCNTL_H
#include <fcntl.h>
+#endif
+#if HAVE_GRP_H
#include <grp.h>
-#ifndef _SQUID_FREEBSD_ /* "Obsolete" Markus Stumpf <maex@Space.NET> */
+#endif
+#if HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_)
#include <malloc.h>
#endif
+#if HAVE_MEMORY_H
#include <memory.h>
+#endif
+#if HAVE_NETDB_H && !defined(_SQUID_NETDB_H_) /* protect NEXTSTEP */
+#define _SQUID_NETDB_H_
#include <netdb.h>
+#endif
+#if HAVE_PWD_H
#include <pwd.h>
+#endif
+#if HAVE_SIGNAL_H
#include <signal.h>
+#endif
+#if HAVE_TIME_H
#include <time.h>
+#endif
+#if HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
+#if HAVE_SYS_TIME_H
#include <sys/time.h>
+#endif
+#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h> /* needs sys/time.h above it */
+#endif
+#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
+#endif
+#if HAVE_NETINET_IN_H
#include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
+#endif
+#if HAVE_SYS_STAT_H
#include <sys/stat.h>
+#endif
+#if HAVE_SYS_UN_H
#include <sys/un.h>
+#endif
+#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
-
-#ifdef HAVE_STRING_H
+#endif
+#if HAVE_LIBC_H
+#include <libc.h>
+#endif
+#if HAVE_STRING_H
#include <string.h>
#endif
-
-#ifdef HAVE_STRINGS_H
+#if HAVE_STRINGS_H
#include <strings.h>
#endif
-
#if HAVE_BSTRING_H
#include <bstring.h>
#endif
-
-#ifdef HAVE_CRYPT_H
+#if HAVE_CRYPT_H
#include <crypt.h>
#endif
-
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
STATS_O,
STATS_VM,
STATS_U,
+ STATS_IO,
SHUTDOWN,
REFRESH,
#ifdef REMOVE_OBJECT
"stats/objects",
"stats/vm_objects",
"stats/utilization",
+ "stats/io",
"shutdown",
"<refresh>",
#ifdef REMOVE_OBJECT
printf("<OPTION VALUE=\"log\">Cache Log\n");
#endif
printf("<OPTION VALUE=\"stats/utilization\">Utilization\n");
+ printf("<OPTION VALUE=\"stats/io\">I/O\n");
printf("<OPTION VALUE=\"stats/objects\">Objects\n");
printf("<OPTION VALUE=\"stats/vm_objects\">VM_Objects\n");
printf("<OPTION VALUE=\"server_list\">Cache Server List\n");
char *makeword(char *line, char stop)
{
int x = 0, y;
- char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
+ char *word = xmalloc(sizeof(char) * (strlen(line) + 1));
for (x = 0; ((line[x]) && (line[x] != stop)); x++)
word[x] = line[x];
/* A utility function from the NCSA httpd cgi-src utils.c */
char *fmakeword(FILE * f, char stop, int *cl)
{
- int wsize;
- char *word;
- int ll;
-
- wsize = 102400;
- ll = 0;
- word = (char *) malloc(sizeof(char) * (wsize + 1));
+ int wsize = 102400;
+ char *word = NULL;
+ int ll = 0;
+ word = xmalloc(sizeof(char) * (wsize + 1));
for (;;) {
word[ll] = (char) fgetc(f);
if (ll == wsize) {
word[ll + 1] = '\0';
wsize += 102400;
- word = (char *) realloc(word, sizeof(char) * (wsize + 1));
+ word = realloc(word, sizeof(char) * (wsize + 1));
}
--(*cl);
if ((word[ll] == stop) || (feof(f)) || (!(*cl))) {
/* A utility function from the NCSA httpd cgi-src utils.c */
char x2c(char *what)
{
- register char digit;
+ char digit;
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
digit *= 16;
/* A utility function from the NCSA httpd cgi-src utils.c */
void unescape_url(char *url)
{
- register int x, y;
+ int x, y;
for (x = 0, y = 0; url[y]; ++x, ++y) {
if ((url[x] = url[y]) == '%') {
/* A utility function from the NCSA httpd cgi-src utils.c */
void plustospace(char *str)
{
- register int x;
+ int x;
for (x = 0; str[x]; x++)
if (str[x] == '+')
printf("Content-type: text/html\r\n\r\n");
if ((agent = getenv("HTTP_USER_AGENT")) != NULL) {
if (!strncasecmp(agent, "Mozilla", 7) ||
+ !strncasecmp(agent, "OmniWeb/2", 9) ||
!strncasecmp(agent, "Netscape", 8)) {
hasTables = TRUE;
}
} else if (!strcmp(operation, "stats/utilization") ||
!strcmp(operation, "Utilization")) {
op = STATS_U;
+ } else if (!strcmp(operation, "stats/io") ||
+ !strcmp(operation, "I/O")) {
+ op = STATS_IO;
} else if (!strcmp(operation, "shutdown")) {
op = SHUTDOWN;
} else if (!strcmp(operation, "refresh")) {
case STATS_O:
case STATS_VM:
case STATS_U:
+ case STATS_IO:
sprintf(msg, "GET cache_object://%s/%s HTTP/1.0\r\n\r\n",
hostname, op_cmds[op]);
break;
printf("<OPTION VALUE=\"log\">Cache Log\n");
#endif
printf("<OPTION VALUE=\"stats/utilization\">Utilization\n");
+ printf("<OPTION VALUE=\"stats/io\">I/O\n");
printf("<OPTION VALUE=\"stats/objects\">Objects\n");
printf("<OPTION VALUE=\"stats/vm_objects\">VM_Objects\n");
printf("<OPTION VALUE=\"server_list\">Cache Server List\n");
case STATS_G:
case STATS_O:
case STATS_VM:
+ case STATS_IO:
case SHUTDOWN:
case REFRESH:
break;
case SERVER:
case LOG:
case STATS_G:
+ case STATS_IO:
case SHUTDOWN:
p_state = 1;
printf("%s", reserve);
static int client_comm_connect(sock, dest_host, dest_port)
int sock; /* Type of communication to use. */
char *dest_host; /* Server's host name. */
- int dest_port; /* Server's port. */
+ u_short dest_port; /* Server's port. */
{
struct hostent *hp;
static struct sockaddr_in to_addr;
if ((hp = gethostbyname(dest_host)) == 0) {
return (-1);
}
- memcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
+ xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
to_addr.sin_port = htons(dest_port);
return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in));
}
-/* $Id: client.cc,v 1.6 1996/05/03 22:56:22 wessels Exp $ */
+/*
+ * $Id: client.cc,v 1.7 1996/07/09 03:41:20 wessels Exp $
+ *
+ * DEBUG: section 0 WWW Client
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include "squid.h"
char *progname;
{
fprintf(stderr, "\
-Usage: %s [-rs] [-h host] [-p port] url\n\
+Usage: %s [-rs] [-i IMS_time] [-h host] [-p port] [-m method] url\n\
Options:\n\
-r Force cache to reload URL.\n\
-s Silent. Do not print data to stdout.\n\
+ -i IMS If-Modified-Since time (in Epoch seconds).\n\
-h host Retrieve URL from cache on hostname. Default is localhost.\n\
-p port Port number of cache. Default is %d.\n\
- -m method Request method, default is GET\n\
+ -m method Request method, default is GET.\n\
", progname, CACHE_HTTP_PORT);
exit(1);
}
static int client_comm_connect(sock, dest_host, dest_port)
int sock; /* Type of communication to use. */
char *dest_host; /* Server's host name. */
- int dest_port; /* Server's port. */
+ u_short dest_port; /* Server's port. */
{
struct hostent *hp;
static struct sockaddr_in to_addr;
if ((hp = gethostbyname(dest_host)) == 0) {
return (-1);
}
- memcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
+ xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
to_addr.sin_port = htons(dest_port);
return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in));
}
-/* $Id: comm.cc,v 1.32 1996/05/03 22:56:23 wessels Exp $ */
+/*
+ * $Id: comm.cc,v 1.33 1996/07/09 03:41:20 wessels Exp $
+ *
+ * DEBUG: section 5 Socket Functions
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
-/* DEBUG: Section 5 comm: socket level functions */
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include "squid.h"
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
/* Block processing new client requests (accepts on ascii port) when we start
* running shy of free file descriptors. For example, under SunOS, we'll keep
* 64 file descriptors free for disk-i/o and connections to remote servers */
int RESERVED_FD = 64;
+struct in_addr any_addr;
#define min(x,y) ((x)<(y)? (x) : (y))
#define max(a,b) ((a)>(b)? (a) : (b))
+struct _RWStateData {
+ char *buf;
+ long size;
+ long offset;
+ int timeout; /* XXX Not used at present. */
+ time_t time; /* XXX Not used at present. */
+ rw_complete_handler *handler;
+ void *handler_data;
+ int handle_immed;
+};
/* GLOBAL */
FD_ENTRY *fd_table = NULL; /* also used in disk.c */
/* STATIC */
-static int *fd_lifetime = NULL;
static void checkTimeouts _PARAMS((void));
static void checkLifetimes _PARAMS((void));
static void Reserve_More_FDs _PARAMS((void));
-static int commSetReuseAddr _PARAMS((int));
+static void commSetReuseAddr _PARAMS((int));
static int examine_select _PARAMS((fd_set *, fd_set *, fd_set *));
-static int commSetNoLinger _PARAMS((int));
-static struct timeval zero_tv;
+static void commSetNoLinger _PARAMS((int));
static void comm_select_incoming _PARAMS((void));
+static int commBind _PARAMS((int s, struct in_addr, u_short port));
+#ifdef TCP_NODELAY
+static void commSetTcpNoDelay _PARAMS((int));
+#endif
+
+static int *fd_lifetime = NULL;
+static struct timeval zero_tv;
/* Return the local port associated with fd. */
-int comm_port(fd)
+u_short comm_local_port(fd)
int fd;
{
struct sockaddr_in addr;
int addr_len = 0;
- if (fd_table[fd].port)
- return fd_table[fd].port;
-
/* If the fd is closed already, just return */
if (!fd_table[fd].openned) {
- debug(5, 0, "comm_port: FD %d has been closed.\n", fd);
- return (COMM_ERROR);
+ debug(5, 0, "comm_local_port: FD %d has been closed.\n", fd);
+ return 0;
}
+ if (fd_table[fd].local_port)
+ return fd_table[fd].local_port;
addr_len = sizeof(addr);
if (getsockname(fd, (struct sockaddr *) &addr, &addr_len)) {
- debug(5, 1, "comm_port: Failed to retrieve TCP/UDP port number for socket: FD %d: %s\n", fd, xstrerror());
- return (COMM_ERROR);
+ debug(5, 1, "comm_local_port: Failed to retrieve TCP/UDP port number for socket: FD %d: %s\n", fd, xstrerror());
+ return 0;
}
- debug(5, 6, "comm_port: FD %d: sockaddr %u.\n", fd, addr.sin_addr.s_addr);
- fd_table[fd].port = ntohs(addr.sin_port);
-
- return fd_table[fd].port;
+ debug(5, 6, "comm_local_port: FD %d: sockaddr %u.\n", fd, addr.sin_addr.s_addr);
+ fd_table[fd].local_port = ntohs(addr.sin_port);
+ return fd_table[fd].local_port;
}
-static int do_bind(s, host, port)
+static int commBind(s, in_addr, port)
int s;
- char *host;
- int port;
+ struct in_addr in_addr;
+ u_short port;
{
struct sockaddr_in S;
- struct in_addr *addr = NULL;
- addr = getAddress(host);
- if (addr == (struct in_addr *) NULL) {
- debug(5, 0, "do_bind: Unknown host: %s\n", host);
- return COMM_ERROR;
- }
memset(&S, '\0', sizeof(S));
S.sin_family = AF_INET;
S.sin_port = htons(port);
- S.sin_addr = *addr;
-
+ S.sin_addr = in_addr;
if (bind(s, (struct sockaddr *) &S, sizeof(S)) == 0)
return COMM_OK;
-
- debug(5, 0, "do_bind: Cannot bind socket FD %d to %s:%d: %s\n",
+ debug(5, 0, "commBind: Cannot bind socket FD %d to %s:%d: %s\n",
s,
- S.sin_addr.s_addr == htonl(INADDR_ANY) ? "*" : inet_ntoa(S.sin_addr),
+ S.sin_addr.s_addr == INADDR_ANY ? "*" : inet_ntoa(S.sin_addr),
port, xstrerror());
return COMM_ERROR;
}
/* Create a socket. Default is blocking, stream (TCP) socket. IO_TYPE
* is OR of flags specified in comm.h. */
-int comm_open(io_type, port, handler, note)
+int comm_open(io_type, addr, port, note)
unsigned int io_type;
- int port;
- int (*handler) (); /* Interrupt handler. */
+ struct in_addr addr;
+ u_short port;
char *note;
{
int new_socket;
FD_ENTRY *conn = NULL;
int sock_type = io_type & COMM_DGRAM ? SOCK_DGRAM : SOCK_STREAM;
- wordlist *p = NULL;
/* Create socket for accepting new connections. */
if ((new_socket = socket(AF_INET, sock_type, 0)) < 0) {
return (COMM_ERROR);
}
/* update fdstat */
- fdstat_open(new_socket, Socket);
+ fdstat_open(new_socket, FD_SOCKET);
conn = &fd_table[new_socket];
memset(conn, '\0', sizeof(FD_ENTRY));
- fd_note(new_socket, note);
+ if (note)
+ fd_note(new_socket, note);
conn->openned = 1;
- if (fcntl(new_socket, F_SETFD, 1) < 0) {
- debug(5, 0, "comm_open: FD %d: failed to set close-on-exec flag: %s\n",
- new_socket, xstrerror());
+ if (!(io_type & COMM_NOCLOEXEC)) {
+ if (fcntl(new_socket, F_SETFD, 1) < 0) {
+ debug(5, 0, "comm_open: FD %d: set close-on-exec failed: %s\n",
+ new_socket, xstrerror());
+ }
}
if (port > 0) {
- if (commSetNoLinger(new_socket) < 0) {
- debug(5, 0, "comm_open: failed to turn off SO_LINGER: %s\n",
- xstrerror());
- }
- if (do_reuse) {
+ commSetNoLinger(new_socket);
+ if (do_reuse)
commSetReuseAddr(new_socket);
- }
- }
- if (port) {
- for (p = getBindAddrList(); p; p = p->next) {
- if (do_bind(new_socket, p->key, port) == COMM_OK)
- break;
- if (p->next == (wordlist *) NULL)
- return COMM_ERROR;
- }
}
- conn->port = port;
+ if (addr.s_addr != INADDR_NONE)
+ if (commBind(new_socket, addr, port) != COMM_OK)
+ return COMM_ERROR;
+ conn->local_port = port;
- if (io_type & COMM_NONBLOCKING) {
- /*
- * Set up the flag NOT to have the socket to wait for message from
- * network forever, but to return -1 when no message is coming in.
- */
-#if defined(O_NONBLOCK) && !defined(_SQUID_SUNOS_) && !defined(_SQUID_SOLARIS_)
- if (fcntl(new_socket, F_SETFL, O_NONBLOCK)) {
- debug(5, 0, "comm_open: FD %d: Failure to set O_NONBLOCK: %s\n",
- new_socket, xstrerror());
- return (COMM_ERROR);
- }
-#else
- if (fcntl(new_socket, F_SETFL, O_NDELAY)) {
- debug(5, 0, "comm_open: FD %d: Failure to set O_NDELAY: %s\n",
- new_socket, xstrerror());
- return (COMM_ERROR);
- }
-#endif /* O_NONBLOCK */
- }
+ if (io_type & COMM_NONBLOCKING)
+ if (commSetNonBlocking(new_socket) == COMM_ERROR)
+ return COMM_ERROR;
+#ifdef TCP_NODELAY
+ if (sock_type == SOCK_STREAM)
+ commSetTcpNoDelay(new_socket);
+#endif
conn->comm_type = io_type;
return new_socket;
}
/*
- * NOTE: set the listen queue to getMaxFD()/4 and rely on the kernel to
+ * NOTE: set the listen queue to FD_SETSIZE/4 and rely on the kernel to
* impose an upper limit. Solaris' listen(3n) page says it has
* no limit on this parameter, but sys/socket.h sets SOMAXCONN
* to 5. HP-UX currently has a limit of 20. SunOS is 5 and
int sock;
{
int x;
- if ((x = listen(sock, getMaxFD() >> 2)) < 0) {
+ if ((x = listen(sock, FD_SETSIZE >> 2)) < 0) {
debug(5, 0, "comm_listen: listen(%d, %d): %s\n",
- getMaxFD() >> 2,
+ FD_SETSIZE >> 2,
sock, xstrerror());
return x;
}
return sock;
}
-
/* Connect SOCK to specified DEST_PORT at DEST_HOST. */
int comm_connect(sock, dest_host, dest_port)
int sock; /* Type of communication to use. */
char *dest_host; /* Server's host name. */
- int dest_port; /* Server's port. */
+ u_short dest_port; /* Server's port. */
{
struct hostent *hp = NULL;
static struct sockaddr_in to_addr;
/* Set up the destination socket address for message to send to. */
to_addr.sin_family = AF_INET;
- if ((hp = ipcache_gethostbyname(dest_host)) == 0) {
+ if ((hp = ipcache_gethostbyname(dest_host, IP_BLOCKING_LOOKUP)) == 0) {
debug(5, 1, "comm_connect: Failure to lookup host: %s.\n", dest_host);
return (COMM_ERROR);
}
- memcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
+ xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
to_addr.sin_port = htons(dest_port);
return comm_connect_addr(sock, &to_addr);
}
int fd;
int lifetime;
{
- if (fd < 0 || fd > getMaxFD())
+ debug(5, 3, "comm_set_fd_lifetime: FD %d lft %d\n", fd, lifetime);
+ if (fd < 0 || fd > FD_SETSIZE)
return 0;
if (lifetime < 0)
return fd_lifetime[fd] = -1;
+ if (shutdown_pending || reread_pending) {
+ /* don't increase the lifetime if something pending */
+ if (fd_lifetime[fd] > -1 && (fd_lifetime[fd] - squid_curtime) < lifetime)
+ return fd_lifetime[fd];
+ }
return fd_lifetime[fd] = (int) squid_curtime + lifetime;
}
case EALREADY:
return COMM_ERROR;
/* NOTREACHED */
+#if EAGAIN != EWOULDBLOCK
+ case EAGAIN:
+#endif
+ case EWOULDBLOCK:
case EINPROGRESS:
status = EINPROGRESS;
break;
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *) &x, &len) >= 0)
errno = x;
default:
- debug(5, 1, "comm_connect_addr: %s:%d: socket failure: %s.\n",
+ debug(5, 1, "connect: %s:%d: %s.\n",
inet_ntoa(address->sin_addr),
ntohs(address->sin_port),
xstrerror());
if (status == COMM_OK) {
lft = comm_set_fd_lifetime(sock, getClientLifetime());
strcpy(conn->ipaddr, inet_ntoa(address->sin_addr));
- conn->port = ntohs(address->sin_port);
+ conn->remote_port = ntohs(address->sin_port);
debug(5, 10, "comm_connect_addr: FD %d (lifetime %d): connected to %s:%d.\n",
- sock, lft, conn->ipaddr, conn->port);
+ sock, lft, conn->ipaddr, conn->remote_port);
} else if (status == EINPROGRESS) {
lft = comm_set_fd_lifetime(sock, getConnectTimeout());
debug(5, 10, "comm_connect_addr: FD %d connection pending, lifetime %d\n",
*me = M;
}
/* fdstat update */
- fdstat_open(sock, Socket);
+ fdstat_open(sock, FD_SOCKET);
conn = &fd_table[sock];
conn->openned = 1;
conn->sender = 0; /* This is an accept, therefore receiver. */
conn->comm_type = listener->comm_type;
strcpy(conn->ipaddr, inet_ntoa(P.sin_addr));
-
+ conn->remote_port = htons(P.sin_port);
+ conn->local_port = htons(M.sin_port);
commSetNonBlocking(sock);
-
return sock;
}
int fd;
{
FD_ENTRY *conn = NULL;
+ struct close_handler *ch = NULL;
if (fd < 0)
return -1;
- if (fdstat_type(fd) == File) {
+ if (fdstat_type(fd) == FD_FILE) {
debug(5, 0, "FD %d: Someone called comm_close() on a File\n", fd);
fatal_dump(NULL);
}
conn = &fd_table[fd];
+ safe_free(conn->rstate);
+ safe_free(conn->wstate);
+
comm_set_fd_lifetime(fd, -1); /* invalidate the lifetime */
debug(5, 5, "comm_close: FD %d\n", fd);
/* update fdstat */
fdstat_close(fd);
- if (conn->close_handler)
- conn->close_handler(fd, conn->close_data);
+ /* Call close handlers */
+ while ((ch = conn->close_handler)) {
+ conn->close_handler = ch->next;
+ ch->handler(fd, ch->data);
+ safe_free(ch);
+ }
memset(conn, '\0', sizeof(FD_ENTRY));
return close(fd);
}
int fd;
{
FD_ENTRY *conn = &fd_table[fd];
-
+ safe_free(conn->rstate);
+ safe_free(conn->wstate);
memset(conn, 0, sizeof(FD_ENTRY));
return 0;
}
int comm_udp_send(fd, host, port, buf, len)
int fd;
char *host;
- int port;
+ u_short port;
char *buf;
int len;
{
/* Set up the destination socket address for message to send to. */
to_addr.sin_family = AF_INET;
- if ((hp = ipcache_gethostbyname(host)) == 0) {
+ if ((hp = ipcache_gethostbyname(host, IP_BLOCKING_LOOKUP)) == 0) {
debug(5, 1, "comm_udp_send: gethostbyname failure: %s: %s\n",
host, xstrerror());
return (COMM_ERROR);
}
- memcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
+ xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
to_addr.sin_port = htons(port);
if ((bytes_sent = sendto(fd, buf, len, 0, (struct sockaddr *) &to_addr,
sizeof(to_addr))) < 0) {
debug(5, 1, "comm_udp_sendto: --> sin_family = %d\n", to_addr->sin_family);
debug(5, 1, "comm_udp_sendto: --> sin_port = %d\n", htons(to_addr->sin_port));
debug(5, 1, "comm_udp_sendto: --> sin_addr = %s\n", inet_ntoa(to_addr->sin_addr));
+ debug(5, 1, "comm_udp_sendto: --> length = %d\n", len);
return COMM_ERROR;
}
return bytes_sent;
FD_ZERO(&read_mask);
FD_ZERO(&write_mask);
- if (theAsciiConnection >= 0 && fdstat_are_n_free_fd(RESERVED_FD))
- fds[N++] = theAsciiConnection;
- if (theUdpConnection >= 0)
- fds[N++] = theUdpConnection;
+ if (theHttpConnection >= 0 && fdstat_are_n_free_fd(RESERVED_FD))
+ fds[N++] = theHttpConnection;
+ if (theInIcpConnection >= 0)
+ fds[N++] = theInIcpConnection;
fds[N++] = 0;
for (i = 0; i < N; i++) {
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
+ if (shutdown_pending || reread_pending) {
+ serverConnectionsClose();
+ ftpServerClose();
+ ipcacheShutdownServers();
+ setSocketShutdownLifetimes();
+ }
nfds = 0;
maxfd = fdstat_biggest_fd() + 1;
for (i = 0; i < maxfd; i++) {
}
}
if (!fdstat_are_n_free_fd(RESERVED_FD)) {
- FD_CLR(theAsciiConnection, &readfds);
+ FD_CLR(theHttpConnection, &readfds);
}
if (shutdown_pending || reread_pending)
debug(5, 2, "comm_select: Still waiting on %d FDs\n", nfds);
if (nfds == 0)
return COMM_SHUTDOWN;
+ if (shutdown_pending || reread_pending)
+ debug(5, 2, "comm_select: Still waiting on %d FDs\n", nfds);
while (1) {
- poll_time.tv_sec = 1;
+ poll_time.tv_sec = sec > 1 ? 1 : 0;
poll_time.tv_usec = 0;
num = select(maxfd, &readfds, &writefds, &exceptfds, &poll_time);
if (num >= 0)
break;
- /* break on interrupt so outer loop will reset FD_SET's */
if (errno == EINTR)
break;
- debug(5, 0, "comm_select: select failure: %s (errno %d).\n",
- xstrerror(), errno);
+ debug(5, 0, "comm_select: select failure: %s\n",
+ xstrerror());
examine_select(&readfds, &writefds, &exceptfds);
return COMM_ERROR;
+ /* NOTREACHED */
}
if (num < 0)
continue;
-
debug(5, num ? 5 : 8, "comm_select: %d sockets ready at %d\n",
- num, squid_curtime);
+ num, (int) squid_curtime);
/* Check lifetime and timeout handlers ONCE each second.
* Replaces brain-dead check every time through the loop! */
*/
comm_select_incoming();
- if ((fd == theUdpConnection) || (fd == theAsciiConnection))
+ if ((fd == theInIcpConnection) || (fd == theHttpConnection))
continue;
if (FD_ISSET(fd, &readfds)) {
return COMM_TIMEOUT;
}
-
-/* Select on fd to see if any io pending. */
-int comm_pending(fd, sec, usec)
- int fd;
- long sec, usec;
-{
- fd_set readfds;
- int num;
- struct timeval timeout;
-
- /* Find a fd ready for reading. */
- FD_ZERO(&readfds);
- FD_SET(fd, &readfds);
-
- while (1) {
- timeout.tv_sec = (time_t) sec;
- timeout.tv_usec = (time_t) usec;
- num = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
- if (num >= 0)
- break;
- switch (errno) {
-#if EAGAIN != EWOULDBLOCK
- case EAGAIN:
-#endif
- case EWOULDBLOCK:
- return COMM_NOMESSAGE;
- case EINTR:
- break; /* if select interrupted, try again */
- default:
- debug(5, 1, "comm_pending: select failure: %s\n", xstrerror());
- return COMM_ERROR;
- }
- }
-
- debug(5, 5, "comm_pending: %d sockets ready for reading\n", num);
-
- if (num && FD_ISSET(fd, &readfds)) {
- return COMM_OK;
- }
- return COMM_TIMEOUT;
-}
-
void comm_set_select_handler(fd, type, handler, client_data)
int fd;
unsigned int type;
int (*handler) ();
void *client_data;
{
-
comm_set_select_handler_plus_timeout(fd, type, handler, client_data, 0);
}
fd_table[fd].lifetime_handler = handler;
fd_table[fd].lifetime_data = client_data;
}
- if (type & COMM_SELECT_CLOSE) {
- fd_table[fd].close_handler = handler;
- fd_table[fd].close_data = client_data;
- }
}
int comm_get_select_handler(fd, type, handler_ptr, client_data_ptr)
return 0; /* XXX What is meaningful? */
}
+void comm_add_close_handler(fd, handler, data)
+ int fd;
+ int (*handler) ();
+ void *data;
+{
+ struct close_handler *new = xmalloc(sizeof(*new));
+
+ debug(5, 5, "comm_add_close_handler: fd=%d handler=0x%p data=0x%p\n", fd, handler, data);
-static int commSetNoLinger(fd)
+ new->handler = handler;
+ new->data = data;
+ new->next = fd_table[fd].close_handler;
+ fd_table[fd].close_handler = new;
+}
+
+void comm_remove_close_handler(fd, handler, data)
int fd;
+ int (*handler) ();
+ void *data;
{
- struct linger L;
+ struct close_handler *p, *last = NULL;
+
+ /* Find handler in list */
+ for (p = fd_table[fd].close_handler; p != NULL; last = p, p = p->next)
+ if (p->handler == handler && p->data == data)
+ break; /* This is our handler */
+ if (!p)
+ fatal_dump("comm_remove_close_handler: Handler not found!\n");
+
+ /* Remove list entry */
+ if (last)
+ last->next = p->next;
+ else
+ fd_table[fd].close_handler = p->next;
+ safe_free(p);
+}
+static void commSetNoLinger(fd)
+ int fd;
+{
+ struct linger L;
L.l_onoff = 0; /* off */
L.l_linger = 0;
-
debug(5, 10, "commSetNoLinger: turning off SO_LINGER on FD %d\n", fd);
- return setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L));
+ if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0)
+ debug(5, 0, "commSetNoLinger: FD %d: %s\n", fd, xstrerror());
}
-static int commSetReuseAddr(fd)
+static void commSetReuseAddr(fd)
int fd;
{
int on = 1;
- int rc;
-
debug(5, 10, "commSetReuseAddr: turning on SO_REUSEADDR on FD %d\n", fd);
- rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
- if (rc < 0)
- debug(5, 1, "commSetReuseAddr: FD=%d: %s\n", fd, xstrerror());
- return rc;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0)
+ debug(5, 1, "commSetReuseAddr: FD %d: %s\n", fd, xstrerror());
}
-int commSetNonBlocking(fd)
+#ifdef TCP_NODELAY
+static void commSetTcpNoDelay(fd)
int fd;
{
- debug(5, 10, "commSetNonBlocking: setting FD %d to non-blocking i/o.\n",
- fd);
- /*
- * Set up the flag NOT to have the socket to wait for message from
- * network forever, but to return -1 when no message is coming in.
- */
+ int on = 1;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0)
+ debug(5, 1, "commSetTcpNoDelay: FD %d: %s\n", fd, xstrerror());
+}
+#endif
+int commSetNonBlocking(fd)
+ int fd;
+{
#if defined(O_NONBLOCK) && !defined(_SQUID_SUNOS_) && !defined(_SQUID_SOLARIS_)
if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
debug(5, 0, "comm_open: FD %d: error setting O_NONBLOCK: %s\n",
fd, xstrerror());
- return (COMM_ERROR);
+ return COMM_ERROR;
}
#else
if (fcntl(fd, F_SETFL, O_NDELAY)) {
debug(5, 0, "comm_open: FD %d: error setting O_NDELAY: %s\n",
fd, xstrerror());
- return (COMM_ERROR);
+ return COMM_ERROR;
}
-#endif /* HPUX */
+#endif
return 0;
}
struct hostent *hp = NULL;
if (name == NULL)
return NULL;
- if ((hp = ipcache_gethostbyname(name)))
+ if ((hp = ipcache_gethostbyname(name, IP_BLOCKING_LOOKUP)))
return hp->h_addr_list;
debug(5, 0, "getAddress: gethostbyname failure: %s: %s\n",
name, xstrerror());
if (name == NULL)
return NULL;
if ((list = getAddressList(name))) {
- memcpy(&first.s_addr, *list, 4);
+ xmemcpy(&first.s_addr, *list, 4);
return (&first);
}
debug(5, 0, "getAddress: gethostbyname failure: %s: %s\n",
*/
int comm_init()
{
- int i, max_fd = getMaxFD();
+ int i;
- fd_table = (FD_ENTRY *) xcalloc(max_fd, sizeof(FD_ENTRY));
+ fd_table = xcalloc(FD_SETSIZE, sizeof(FD_ENTRY));
+ meta_data.misc += FD_SETSIZE * sizeof(FD_ENTRY);
/* Keep a few file descriptors free so that we don't run out of FD's
* after accepting a client but before it opens a socket or a file.
- * Since getMaxFD can be as high as several thousand, don't waste them */
- RESERVED_FD = min(100, getMaxFD() / 4);
+ * Since FD_SETSIZE can be as high as several thousand, don't waste them */
+ RESERVED_FD = min(100, FD_SETSIZE / 4);
/* hardwired lifetimes */
- fd_lifetime = (int *) xmalloc(sizeof(int) * max_fd);
- for (i = 0; i < max_fd; i++)
+ fd_lifetime = xmalloc(sizeof(int) * FD_SETSIZE);
+ for (i = 0; i < FD_SETSIZE; i++)
comm_set_fd_lifetime(i, -1); /* denotes invalid */
+ meta_data.misc += FD_SETSIZE * sizeof(int);
zero_tv.tv_sec = 0;
zero_tv.tv_usec = 0;
+ any_addr.s_addr = inet_addr("0.0.0.0");
return 0;
}
fd_set write_x;
fd_set except_x;
int num;
- int maxfd = getMaxFD();
struct timeval tv;
+ struct close_handler *ch = NULL;
+ struct close_handler *next = NULL;
FD_ENTRY *f = NULL;
debug(5, 0, "examine_select: Examining open file descriptors...\n");
- for (fd = 0; fd < maxfd; fd++) {
+ for (fd = 0; fd < FD_SETSIZE; fd++) {
FD_ZERO(&read_x);
FD_ZERO(&write_x);
FD_ZERO(&except_x);
f->read_handler,
f->write_handler,
f->except_handler);
+ for (ch = f->close_handler; ch; ch = ch->next)
+ debug(5, 0, " close handler: %p\n", ch->handler);
if (f->close_handler) {
- debug(5, 0, "examine_select: Calling Close Handler\n");
- f->close_handler(fd, f->close_data);
+ for (ch = f->close_handler; ch; ch = next) {
+ next = ch->next;
+ ch->handler(fd, ch->data);
+ safe_free(ch);
+ }
} else if (f->lifetime_handler) {
debug(5, 0, "examine_select: Calling Lifetime Handler\n");
f->lifetime_handler(fd, f->lifetime_data);
}
}
}
- debug(5, 0, "examine_select: Finished examining open file descriptors.\n");
return 0;
}
int fd;
int (*tmp) () = NULL;
FD_ENTRY *f = NULL;
- int maxfd = fdstat_biggest_fd() + 1;
/* scan for timeout */
- for (fd = 0; fd < maxfd; ++fd) {
+ for (fd = 0; fd < FD_SETSIZE; ++fd) {
f = &fd_table[fd];
if ((f->timeout_handler) &&
(f->timeout_time <= squid_curtime)) {
static void checkLifetimes()
{
int fd;
- int max_fd = getMaxFD();
time_t lft;
- int (*tmp_local) () = NULL;
- int use_lifetime_handler = 0;
- int use_read = 0;
-
- /* scan for hardwired lifetime expires, do the timeouts first though */
- for (fd = 0; fd < max_fd; fd++) {
- lft = comm_get_fd_lifetime(fd);
- if ((lft != -1) && (lft < squid_curtime)) {
- if (fd_table[fd].lifetime_handler != NULL) {
- use_lifetime_handler = 1;
- tmp_local = fd_table[fd].lifetime_handler;
- fd_table[fd].lifetime_handler = 0; /* reset it */
- } else if (fd_table[fd].read_handler != NULL) {
- use_read = 1;
- tmp_local = fd_table[fd].read_handler;
- fd_table[fd].read_handler = 0; /* reset it */
- } else if (fd_table[fd].write_handler != NULL) {
- use_read = 0;
- tmp_local = fd_table[fd].write_handler;
- fd_table[fd].write_handler = 0; /* reset it */
- } else {
- use_read = 0;
- tmp_local = NULL;
- }
- if (tmp_local) {
- if (use_lifetime_handler) {
- debug(5, 2, "checkLifetimes: FD %d lifetime expire: %d < %d (Lifetime handler %p)\n",
- fd, lft, squid_curtime, tmp_local);
- } else {
- debug(5, 2, "checkLifetimes: FD %d lifetime expire: %d < %d (%s handler %p)\n",
- fd, lft, squid_curtime,
- use_read ? "read" : "write", tmp_local);
- }
- } else {
- debug(5, 1, "checkLifetimes: FD %d lifetime expire: %d < %d (handler not available.)\n",
- fd, lft, squid_curtime);
- }
- if (tmp_local != NULL) {
- if (use_lifetime_handler) {
- tmp_local(fd, fd_table[fd].lifetime_data);
- } else {
- /*
- * we close(2) first so that the handler fails and
- * deallocates the structure.
- */
- (void) close(fd);
- debug(5, 0, "checkLifetimes: Forcing close on FD %d\n", fd);
- tmp_local(fd, use_read ? fd_table[fd].read_data :
- fd_table[fd].write_data);
- }
- if (fd_table[fd].openned) {
- /* hmm.. still openned. do full comm_close */
- debug(5, 5, "checkLifetimes: FD %d lifetime expire: %d < %d : Handler did not close the socket.\n comm_select will do.\n",
- fd, lft, squid_curtime);
- comm_close(fd);
- } else {
- /* seems like handle closed it.
- * clean up fd_table just to make sure */
- debug(5, 5, "checkLifetimes: FD %d lifetime expire: %d : Handler closed the socket.\n",
- fd, lft);
- /* just to make sure here */
- comm_cleanup_fd_entry(fd);
- }
- } else {
- /* no handle. do full comm_close */
- debug(5, 5, "checkLifetimes: FD %d lifetime expire: %d < %d : No handler to close the socket.\n comm_select will do.\n",
- fd, lft, squid_curtime);
- comm_close(fd);
- }
+ int (*func) () = NULL;
+
+ for (fd = 0; fd < FD_SETSIZE; fd++) {
+ if ((lft = comm_get_fd_lifetime(fd)) == -1)
+ continue;
+ if (lft > squid_curtime)
+ continue;
+ debug(5, 5, "checkLifetimes: FD %d Expired\n", fd);
+ if ((func = fd_table[fd].lifetime_handler)) {
+ debug(5, 5, "checkLifetimes: FD %d: Calling lifetime handler\n", fd);
+ func(fd, fd_table[fd].lifetime_data);
+ fd_table[fd].lifetime_handler = NULL;
+ } else if ((func = fd_table[fd].read_handler)) {
+ debug(5, 5, "checkLifetimes: FD %d: Calling read handler\n", fd);
+ func(fd, fd_table[fd].read_data);
+ fd_table[fd].read_handler = NULL;
+ } else if ((func = fd_table[fd].read_handler)) {
+ debug(5, 5, "checkLifetimes: FD %d: Calling read handler\n", fd);
+ func(fd, fd_table[fd].read_data);
+ fd_table[fd].read_handler = NULL;
+ } else if ((func = fd_table[fd].write_handler)) {
+ debug(5, 5, "checkLifetimes: FD %d: Calling write handler\n", fd);
+ func(fd, fd_table[fd].write_data);
+ fd_table[fd].write_handler = NULL;
+ } else {
+ debug(5, 5, "checkLifetimes: FD %d: No handlers, calling comm_close()\n", fd);
+ comm_close(fd);
+ comm_cleanup_fd_entry(fd);
+ }
+ if (fd_table[fd].openned) {
+ /* still opened */
+ debug(5, 5, "checkLifetimes: FD %d: Forcing comm_close()\n", fd);
+ comm_close(fd);
+ comm_cleanup_fd_entry(fd);
}
}
}
*/
static void Reserve_More_FDs()
{
- if (RESERVED_FD < getMaxFD() - 64) {
+ if (RESERVED_FD < FD_SETSIZE - 64) {
RESERVED_FD = RESERVED_FD + 1;
- } else if (RESERVED_FD == getMaxFD() - 64) {
+ } else if (RESERVED_FD == FD_SETSIZE - 64) {
RESERVED_FD = RESERVED_FD + 1;
debug(5, 0, "Don't you have a tiny open-file table size of %d\n",
- getMaxFD() - RESERVED_FD);
+ FD_SETSIZE - RESERVED_FD);
}
}
}
return (-1);
}
+
+/* Read from FD. */
+static int commHandleRead(fd, state)
+ int fd;
+ RWStateData *state;
+{
+ int len;
+
+ len = read(fd, state->buf + state->offset, state->size - state->offset);
+ debug(5, 5, "commHandleRead: FD %d: read %d bytes\n", fd, len);
+
+ if (len <= 0) {
+ switch (errno) {
+#if EAGAIN != EWOULDBLOCK
+ case EAGAIN:
+#endif
+ case EWOULDBLOCK:
+ /* reschedule self */
+ comm_set_select_handler(fd,
+ COMM_SELECT_READ,
+ (PF) commHandleRead,
+ state);
+ return COMM_OK;
+ default:
+ /* Len == 0 means connection closed; otherwise would not have been
+ * called by comm_select(). */
+ debug(5, len == 0 ? 2 : 1, "commHandleRead: FD %d: read failure: %s\n",
+ fd, len == 0 ? "connection closed" : xstrerror());
+ fd_table[fd].rstate = NULL; /* The handler may issue a new read */
+ /* Notify caller that we failed */
+ state->handler(fd,
+ state->buf,
+ state->offset,
+ COMM_ERROR,
+ state->handler_data);
+ safe_free(state);
+ return COMM_ERROR;
+ }
+ }
+ state->offset += len;
+
+ /* Call handler if we have read enough */
+ if (state->offset >= state->size || state->handle_immed) {
+ fd_table[fd].rstate = NULL; /* The handler may issue a new read */
+ state->handler(fd,
+ state->buf,
+ state->offset,
+ COMM_OK,
+ state->handler_data);
+ safe_free(state);
+ } else {
+ /* Reschedule until we are done */
+ comm_set_select_handler(fd,
+ COMM_SELECT_READ,
+ (PF) commHandleRead,
+ state);
+ }
+ return COMM_OK;
+}
+
+/* Select for reading on FD, until SIZE bytes are received. Call
+ * HANDLER when complete. */
+void comm_read(fd, buf, size, timeout, immed, handler, handler_data)
+ int fd;
+ char *buf;
+ int size;
+ int timeout;
+ int immed; /* Call handler immediately when data available */
+ rw_complete_handler *handler;
+ void *handler_data;
+{
+ RWStateData *state = NULL;
+
+ debug(5, 5, "comm_read: FD %d: sz %d: tout %d: hndl %p: data %p.\n",
+ fd, size, timeout, handler, handler_data);
+
+ if (fd_table[fd].rstate) {
+ debug(5, 1, "comm_read: WARNING! FD %d: A comm_read is already active.\n", fd);
+ safe_free(fd_table[fd].rstate);
+ }
+ state = xcalloc(1, sizeof(RWStateData));
+ fd_table[fd].rstate = state;
+ state->buf = buf;
+ state->size = size;
+ state->offset = 0;
+ state->handler = handler;
+ state->timeout = timeout;
+ state->handle_immed = immed;
+ state->time = squid_curtime;
+ state->handler_data = handler_data;
+ comm_set_select_handler(fd,
+ COMM_SELECT_READ,
+ (PF) commHandleRead,
+ state);
+}
+
+/* Write to FD. */
+static void commHandleWrite(fd, state)
+ int fd;
+ RWStateData *state;
+{
+ int len = 0;
+ int nleft;
+
+ debug(5, 5, "commHandleWrite: FD %d: state=%p, off %d, sz %d.\n",
+ fd, state, state->offset, state->size);
+
+ nleft = state->size - state->offset;
+ len = write(fd, state->buf + state->offset, nleft);
+
+ if (len == 0) {
+ /* Note we even call write if nleft == 0 */
+ /* We're done */
+ if (nleft != 0)
+ debug(5, 2, "commHandleWrite: FD %d: write failure: connection closed with %d bytes remaining.\n", fd, nleft);
+ fd_table[fd].wstate = NULL;
+ if (state->handler)
+ state->handler(fd,
+ state->buf,
+ state->offset,
+ nleft ? COMM_ERROR : COMM_OK,
+ state->handler_data);
+ else
+ xfree(state->buf);
+ safe_free(state);
+ return;
+ } else if (len < 0) {
+ /* An error */
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ /* XXX: Re-install the handler rather than giving up. I hope
+ * this doesn't freeze this socket due to some random OS bug
+ * returning EWOULDBLOCK indefinitely. Ought to maintain a
+ * retry count in state? */
+ debug(5, 10, "commHandleWrite: FD %d: write failure: %s.\n",
+ fd, xstrerror());
+ comm_set_select_handler(fd,
+ COMM_SELECT_WRITE,
+ (PF) commHandleWrite,
+ state);
+ return;
+ }
+ debug(5, 2, "commHandleWrite: FD %d: write failure: %s.\n",
+ fd, xstrerror());
+ /* Notify caller that we failed */
+ fd_table[fd].wstate = NULL;
+ if (state->handler)
+ state->handler(fd,
+ state->buf,
+ state->offset,
+ COMM_ERROR,
+ state->handler_data);
+ else
+ xfree(state->buf);
+ safe_free(state);
+ return;
+ } else {
+ /* A successful write, continue */
+ state->offset += len;
+ if (state->offset < state->size) {
+ /* Not done, reinstall the write handler and write some more */
+ comm_set_select_handler(fd,
+ COMM_SELECT_WRITE,
+ (PF) commHandleWrite,
+ state);
+ return;
+ }
+ fd_table[fd].wstate = NULL;
+ /* Notify caller that the write is complete */
+ if (state->handler)
+ state->handler(fd,
+ state->buf,
+ state->offset,
+ COMM_OK,
+ state->handler_data);
+ else
+ xfree(state->buf);
+ safe_free(state);
+ }
+}
+
+
+
+/* Select for Writing on FD, until SIZE bytes are sent. Call
+ * * HANDLER when complete. */
+void comm_write(fd, buf, size, timeout, handler, handler_data)
+ int fd;
+ char *buf;
+ int size;
+ int timeout;
+ rw_complete_handler *handler;
+ void *handler_data;
+{
+ RWStateData *state = NULL;
+
+ debug(5, 5, "comm_write: FD %d: sz %d: tout %d: hndl %p: data %p.\n",
+ fd, size, timeout, handler, handler_data);
+
+ if (fd_table[fd].wstate) {
+ debug(5, 1, "comm_write: WARNING! FD %d: A comm_write is already active.\n", fd);
+ safe_free(fd_table[fd].wstate);
+ }
+ state = xcalloc(1, sizeof(RWStateData));
+ state->buf = buf;
+ state->size = size;
+ state->offset = 0;
+ state->handler = handler;
+ state->timeout = timeout;
+ state->time = squid_curtime;
+ state->handler_data = handler_data;
+ comm_set_select_handler(fd,
+ COMM_SELECT_WRITE,
+ (PF) commHandleWrite,
+ fd_table[fd].wstate = state);
+}
+/*
+ * $Id: debug.cc,v 1.18 1996/07/09 03:41:21 wessels Exp $
+ *
+ * DEBUG: section 0 Debug Routines
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
-/* $Id: debug.cc,v 1.17 1996/04/17 17:14:43 wessels Exp $ */
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include "squid.h"
}
}
-void _db_init(logfile)
+void _db_init(logfile, options)
char *logfile;
+ char *options;
{
int i;
char *p = NULL;
for (i = 0; i < MAX_DEBUG_SECTIONS; i++)
debugLevels[i] = -1;
- if ((p = getDebugOptions())) {
- p = xstrdup(p);
- for (s = strtok(p, w_space); s; s = strtok(NULL, w_space)) {
+ if (options) {
+ p = xstrdup(options);
+ for (s = strtok(p, w_space); s; s = strtok(NULL, w_space))
debugArg(s);
- }
xfree(p);
}
debugOpenLog(logfile);
-#if HAVE_SYSLOG
+#if HAVE_SYSLOG && defined(LOG_LOCAL4)
if (syslog_enable)
openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
#endif /* HAVE_SYSLOG */
/* Close and reopen the log. It may have been renamed "manually"
* before HUP'ing us. */
if (debug_log != stderr)
- debugOpenLog(debug_log_file);
+ debugOpenLog(getCacheLogFile());
}
-/* $Id: disk.cc,v 1.12 1996/05/01 22:36:27 wessels Exp $ */
-
-/* DEBUG: Section 6 disk: disk I/O routines */
+/*
+ * $Id: disk.cc,v 1.13 1996/07/09 03:41:22 wessels Exp $
+ *
+ * DEBUG: section 6 Disk I/O Routines
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include "squid.h"
dwrite_q *write_q_tail;
} FileEntry;
-
/* table for FILE variable, write lock and queue. Indexed by fd. */
FileEntry *file_table;
-extern int getMaxFD();
-extern void fatal_dump _PARAMS((char *));
-
/* initialize table */
int disk_init()
{
- int fd, max_fd = getMaxFD();
-
- file_table = (FileEntry *) xmalloc(sizeof(FileEntry) * max_fd);
- memset(file_table, '\0', sizeof(FileEntry) * max_fd);
+ int fd;
- for (fd = 0; fd < max_fd; fd++) {
+ file_table = xcalloc(FD_SETSIZE, sizeof(FileEntry));
+ meta_data.misc += FD_SETSIZE * sizeof(FileEntry);
+ for (fd = 0; fd < FD_SETSIZE; fd++) {
file_table[fd].filename[0] = '\0';
file_table[fd].at_eof = NO;
file_table[fd].open_stat = NOT_OPEN;
return (DISK_ERROR);
}
/* update fdstat */
- fdstat_open(fd, File);
+ fdstat_open(fd, FD_FILE);
/* init table */
strncpy(file_table[fd].filename, path, MAX_FILE_NAME_LEN);
file_table[fd].write_q = NULL;
conn = &fd_table[fd];
- memset(conn, 0, sizeof(FD_ENTRY));
-
- conn->port = 0;
- conn->handler = NULL;
-
- /* set non-blocking mode */
-#if defined(O_NONBLOCK) && !defined(_SQUID_SUNOS_) && !defined(_SQUID_SOLARIS_)
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- debug(6, 0, "file_open: FD %d: Failure to set O_NONBLOCK: %s\n",
- fd, xstrerror());
- return DISK_ERROR;
- }
-#else
- if (fcntl(fd, F_SETFL, O_NDELAY) < 0) {
- debug(6, 0, "file_open: FD %d: Failure to set O_NDELAY: %s\n",
- fd, xstrerror());
+ memset(conn, '\0', sizeof(FD_ENTRY));
+ if (commSetNonBlocking(fd) == COMM_ERROR)
return DISK_ERROR;
- }
-#endif /* O_NONBLOCK */
conn->comm_type = COMM_NONBLOCKING;
-
return fd;
}
FD_ENTRY *conn;
/* update fdstat */
- fdstat_open(fd, File);
+ fdstat_open(fd, FD_FILE);
/* init table */
strncpy(file_table[fd].filename, path, MAX_FILE_NAME_LEN);
file_table[fd].write_q = NULL;
conn = &fd_table[fd];
- memset(conn, 0, sizeof(FD_ENTRY));
-
- conn->port = 0;
- conn->handler = NULL;
-
+ memset(conn, '\0', sizeof(FD_ENTRY));
conn->comm_type = COMM_NONBLOCKING;
-
return fd;
}
file_table[fd].write_daemon = NOT_PRESENT;
file_table[fd].filename[0] = '\0';
- if (fdstat_type(fd) == Socket) {
+ if (fdstat_type(fd) == FD_SOCKET) {
debug(6, 0, "FD %d: Someone called file_close() on a socket\n", fd);
fatal_dump(NULL);
}
return DISK_ERROR;
}
-
-/* return a opened fd associate with given path name. */
-/* return DISK_FILE_NOT_FOUND if not found. */
-int file_get_fd(filename)
- char *filename;
-{
- int fd, max_fd = getMaxFD();
- for (fd = 1; fd < max_fd; fd++) {
- if (file_table[fd].open_stat == OPEN) {
- if (strncmp(file_table[fd].filename, filename, MAX_FILE_NAME_LEN) == 0) {
- return fd;
- }
- }
- }
- return DISK_FILE_NOT_FOUND;
-}
-
/* grab a writing lock for file */
int file_write_lock(fd)
int fd;
return DISK_OK;
default:
/* disk i/o failure--flushing all outstanding writes */
- debug(6, 1, "diskHandleWrite: disk write error %s\n",
- xstrerror());
+ debug(6, 1, "diskHandleWrite: FD %d: disk write error: %s\n",
+ fd, xstrerror());
entry->write_daemon = NOT_PRESENT;
entry->write_pending = NO_WRT_PENDING;
/* call finish handler */
return DISK_WRT_WRONG_CODE;
}
/* if we got here. Caller is eligible to write. */
- wq = (dwrite_q *) xcalloc(1, sizeof(dwrite_q));
+ wq = xcalloc(1, sizeof(dwrite_q));
wq->buf = ptr_to_buf;
{
dread_ctrl *ctrl_dat;
- ctrl_dat = (dread_ctrl *) xmalloc(sizeof(dread_ctrl));
- memset(ctrl_dat, '\0', sizeof(dread_ctrl));
+ ctrl_dat = xcalloc(1, sizeof(dread_ctrl));
ctrl_dat->fd = fd;
ctrl_dat->offset = offset;
ctrl_dat->req_len = req_len;
int end_pos;
int st_pos;
int used_bytes;
- char temp_line[DISK_LINE_LEN];
+ static char temp_line[DISK_LINE_LEN];
lseek(fd, walk_dat->offset, SEEK_SET);
file_table[fd].at_eof = NO;
{
dwalk_ctrl *walk_dat;
- walk_dat = (dwalk_ctrl *) xmalloc(sizeof(dwalk_ctrl));
- memset(walk_dat, '\0', sizeof(dwalk_ctrl));
+ walk_dat = xcalloc(1, sizeof(dwalk_ctrl));
walk_dat->fd = fd;
walk_dat->offset = 0;
- walk_dat->buf = (void *) xcalloc(1, DISK_LINE_LEN);
+ walk_dat->buf = xcalloc(1, DISK_LINE_LEN);
walk_dat->cur_len = 0;
walk_dat->handler = handler;
walk_dat->client_data = client_data;
-/* $Id: dnsserver.cc,v 1.6 1996/05/03 22:56:24 wessels Exp $ */
+/*
+ * $Id: dnsserver.cc,v 1.7 1996/07/09 03:41:22 wessels Exp $
+ *
+ * DEBUG: section 0 DNS Resolver
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include "squid.h"
+#if HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#if HAVE_RESOLV_H
+#include <resolv.h>
+#endif
extern int h_errno;
char *t = NULL;
char buf[256];
int socket_from_cache, fd;
- int a1, a2, a3, a4;
int addr_count = 0;
int alias_count = 0;
int i;
char *dnsServerPathname = NULL;
+ int dnsServerTCP = 0;
int c;
extern char *optarg;
- while ((c = getopt(argc, argv, "vhdp:")) != -1)
+#if HAVE_RES_INIT
+ res_init();
+#ifdef RES_DEFNAMES
+ _res.options &= ~RES_DEFNAMES;
+#endif
+#ifdef RES_DNSRCH
+ _res.options &= ~RES_DNSRCH;
+#endif
+#endif
+
+ while ((c = getopt(argc, argv, "vhdtp:")) != -1) {
switch (c) {
case 'v':
case 'h':
case 'p':
dnsServerPathname = xstrdup(optarg);
break;
+ case 't':
+ dnsServerTCP = 1;
+ break;
default:
fprintf(stderr, "usage: dnsserver -h -d -p socket-filename\n");
exit(1);
break;
}
+ }
socket_from_cache = 3;
/* accept DNS look up from ipcache */
- if (dnsServerPathname) {
- fd = accept(socket_from_cache, (struct sockaddr *) 0, (int *) 0);
- unlink(dnsServerPathname);
+ if (dnsServerPathname || dnsServerTCP) {
+ fd = accept(socket_from_cache, NULL, NULL);
+ if (dnsServerPathname)
+ unlink(dnsServerPathname);
if (fd < 0) {
fprintf(stderr, "dnsserver: accept: %s\n", xstrerror());
exit(1);
memset(request, '\0', 256);
/* read from ipcache */
- if (fgets(request, 255, stdin) == (char *) NULL)
+ if (fgets(request, 255, stdin) == NULL)
exit(1);
if ((t = strrchr(request, '\n')) != NULL)
*t = '\0'; /* strip NL */
continue;
}
/* check if it's already an IP address in text form. */
- if (sscanf(request, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) == 4) {
+ if (inet_addr(request) != INADDR_NONE) {
printf("$name %s\n", request);
printf("$h_name %s\n", request);
printf("$h_len %d\n", 4);
fflush(logfile);
}
printf("$fail %s\n", request);
- printf("$message %s\n", msg[0] ? msg : "Unknown Error");
+ printf("$message %s", msg[0] ? msg : "Unknown Error\n");
printf("$end\n");
fflush(stdout);
continue;
printf("$ipcount %d\n", addr_count);
for (i = 0; i < addr_count; i++) {
struct in_addr addr;
- memcpy((char *) &addr, result->h_addr_list[i], result->h_length);
+ xmemcpy((char *) &addr, result->h_addr_list[i], result->h_length);
printf("%s\n", inet_ntoa(addr));
}
-/* $Id: errorpage.cc,v 1.21 1996/05/01 22:36:28 wessels Exp $ */
-
-/* DEBUG: Section 4 errorpage: Error printing routines */
+/*
+ * $Id: errorpage.cc,v 1.22 1996/07/09 03:41:23 wessels Exp $
+ *
+ * DEBUG: section 4 Error Generation
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
#include "squid.h"
-
-
#define SQUID_ERROR_MSG_P1 "\
<TITLE>ERROR: The requested URL could not be retrieved</TITLE>\n\
<H2>The requested URL could not be retrieved</H2>\n\
char *tmp_error_buf;
/* LOCAL */
-static char *tbuf;
-
-int log_errors = 1;
+static char *tbuf = NULL;
void errorInitialize()
{
- tmp_error_buf = (char *) xmalloc(MAX_URL * 4);
- tbuf = (char *) xmalloc(MAX_URL * 3);
+ tmp_error_buf = xmalloc(MAX_URL * 4);
+ tbuf = xmalloc(MAX_URL * 3);
+ meta_data.misc += MAX_URL * 7;
}
-
void squid_error_entry(entry, type, msg)
StoreEntry *entry;
int type;
appname,
version_string,
getMyHostname());
- if (!log_errors)
- return tmp_error_buf;
+ strcat(tmp_error_buf, tbuf);
return tmp_error_buf;
}
char *address;
int code;
{
- int index;
-
*tmp_error_buf = '\0';
if (type < ERR_MIN || type > ERR_MAX)
- fatal_dump("squid_error_url: type out of range.");
- index = (int) (type - ERR_MIN);
+ fatal_dump("squid_error_request: type out of range.");
sprintf(tmp_error_buf, "HTTP/1.0 %d Cache Detected Error\r\nContent-type: text/html\r\n\r\n", code);
sprintf(tbuf, SQUID_REQUEST_ERROR_MSG,
version_string,
getMyHostname());
strcat(tmp_error_buf, tbuf);
- if (!log_errors)
- return tmp_error_buf;
return tmp_error_buf;
}
-/* $Id: filemap.cc,v 1.7 1996/03/29 21:19:19 wessels Exp $ */
-
-/* DEBUG: Section 8 filemap: swap file bitmap functions */
+/*
+ * $Id: filemap.cc,v 1.8 1996/07/09 03:41:24 wessels Exp $
+ *
+ * DEBUG: section 8 Swap File Bitmap
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include "squid.h"
int n; /* Number of files */
{
fm = xcalloc(1, sizeof(fileMap));
-
fm->max_n_files = n;
fm->nwords = n >> LONG_BIT_SHIFT;
debug(8, 1, "file_map_create: creating space for %d files\n", n);
debug(8, 5, "--> %d words of %d bytes each\n",
fm->nwords, sizeof(unsigned long));
- fm->file_map = (unsigned long *) xcalloc(fm->nwords, sizeof(unsigned long));
+ fm->file_map = xcalloc(fm->nwords, sizeof(unsigned long));
+ meta_data.misc += fm->nwords * sizeof(unsigned long);
return (fm);
}
-/* $Id: ftp.cc,v 1.39 1996/05/03 22:56:25 wessels Exp $ */
+/*
+ * $Id: ftp.cc,v 1.40 1996/07/09 03:41:25 wessels Exp $
+ *
+ * DEBUG: section 9 File Transfer Protocol (FTP)
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
/*
- * DEBUG: Section 9 ftp: FTP
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
-#define FTP_DELETE_GAP (64*1024)
-#define READBUFSIZ 4096
+#define FTP_DELETE_GAP (1<<18)
#define MAGIC_MARKER "\004\004\004" /* No doubt this should be more configurable */
#define MAGIC_MARKER_SZ 3
static char ftpASCII[] = "A";
static char ftpBinary[] = "I";
-static char localhost[] = "127.0.0.1";
-static int ftpget_server_pipe = -1;
+static int ftpget_server_read = -1;
+static int ftpget_server_write = -1;
+static u_short ftpget_port = 0;
typedef struct _Ftpdata {
StoreEntry *entry;
char *icp_page_ptr; /* Used to send proxy-http request:
* put_free_8k_page(me) if the lifetime
* expires */
- char *icp_rwd_ptr; /* When a lifetime expires during the
- * middle of an icpwrite, don't lose the
- * icpReadWriteData */
int got_marker; /* denotes end of successful request */
int reply_hdr_state;
} FtpData;
-
/* Local functions */
static int ftpStateFree _PARAMS((int fd, FtpData * ftpState));
static void ftpProcessReplyHeader _PARAMS((FtpData * data, char *buf, int size));
/* Global functions not declared in ftp.h */
void ftpLifetimeExpire _PARAMS((int fd, FtpData * data));
int ftpReadReply _PARAMS((int fd, FtpData * data));
-void ftpSendComplete _PARAMS((int fd, char *buf, int size, int errflag, FtpData * data));
+void ftpSendComplete _PARAMS((int fd, char *buf, int size, int errflag, void *ftpData));
void ftpSendRequest _PARAMS((int fd, FtpData * data));
void ftpConnInProgress _PARAMS((int fd, FtpData * data));
void ftpServerClose _PARAMS((void));
{
if (ftpState == NULL)
return 1;
+ storeUnlockObject(ftpState->entry);
if (ftpState->reply_hdr) {
put_free_8k_page(ftpState->reply_hdr);
ftpState->reply_hdr = NULL;
put_free_8k_page(ftpState->icp_page_ptr);
ftpState->icp_page_ptr = NULL;
}
- if (ftpState->icp_rwd_ptr)
- safe_free(ftpState->icp_rwd_ptr);
+ requestUnlink(ftpState->request);
xfree(ftpState);
return 0;
}
char *buf; /* chunk just read by ftpReadReply() */
int size;
{
- char *s = NULL;
char *t = NULL;
- char *t1 = NULL;
- char *t2 = NULL;
StoreEntry *entry = data->entry;
- char *headers = NULL;
int room;
int hdr_len;
struct _http_reply *reply = NULL;
data->reply_hdr_state += 2;
return;
}
- /* need to take the lowest, non-zero pointer to the end of the headers.
- * some objects have \n\n separating header and body, but \r\n\r\n in
- * body text. */
- t1 = strstr(data->reply_hdr, "\r\n\r\n");
- t2 = strstr(data->reply_hdr, "\n\n");
- if (t1 && t2)
- t = t2 < t1 ? t2 : t1;
- else
- t = t2 ? t2 : t1;
+ /* Find the end of the headers */
+ t = mime_headers_end(data->reply_hdr);
if (!t)
return; /* headers not complete */
- t += (t == t1 ? 4 : 2);
+ /* Cut after end of headers */
*t = '\0';
reply = entry->mem_obj->reply;
reply->hdr_sz = t - data->reply_hdr;
data->reply_hdr_state++;
}
if (data->reply_hdr_state == 1) {
- headers = xstrdup(data->reply_hdr);
data->reply_hdr_state++;
debug(11, 9, "GOT HTTP REPLY HDR:\n---------\n%s\n----------\n",
data->reply_hdr);
- t = strtok(headers, "\n");
- while (t) {
- s = t + strlen(t);
- while (*s == '\r')
- *s-- = '\0';
- if (!strncasecmp(t, "HTTP", 4)) {
- sscanf(t + 1, "%lf", &reply->version);
- if ((t = strchr(t, ' '))) {
- t++;
- reply->code = atoi(t);
- }
- } else if (!strncasecmp(t, "Content-type:", 13)) {
- if ((t = strchr(t, ' '))) {
- t++;
- strncpy(reply->content_type, t, HTTP_REPLY_FIELD_SZ - 1);
- }
- } else if (!strncasecmp(t, "Content-length:", 15)) {
- if ((t = strchr(t, ' '))) {
- t++;
- reply->content_length = atoi(t);
- }
- } else if (!strncasecmp(t, "Date:", 5)) {
- if ((t = strchr(t, ' '))) {
- t++;
- strncpy(reply->date, t, HTTP_REPLY_FIELD_SZ - 1);
- }
- } else if (!strncasecmp(t, "Expires:", 8)) {
- if ((t = strchr(t, ' '))) {
- t++;
- strncpy(reply->expires, t, HTTP_REPLY_FIELD_SZ - 1);
- }
- } else if (!strncasecmp(t, "Last-Modified:", 14)) {
- if ((t = strchr(t, ' '))) {
- t++;
- strncpy(reply->last_modified, t, HTTP_REPLY_FIELD_SZ - 1);
- }
- }
- t = strtok(NULL, "\n");
- }
- safe_free(headers);
+ /* Parse headers into reply structure */
+ httpParseHeaders(data->reply_hdr, reply);
+ /* Check if object is cacheable or not based on reply code */
if (reply->code)
debug(11, 3, "ftpProcessReplyHeader: HTTP CODE: %d\n", reply->code);
switch (reply->code) {
if (BIT_TEST(entry->flag, CACHABLE))
storeSetPublicKey(entry);
break;
+ case 302: /* Moved Temporarily */
case 304: /* Not Modified */
case 401: /* Unauthorized */
case 407: /* Proxy Authentication Required */
int fd;
FtpData *data;
{
- static char buf[READBUFSIZ];
+ static char buf[SQUID_TCP_SO_RCVBUF];
int len;
int clen;
int off;
+ int bin;
StoreEntry *entry = NULL;
entry = data->entry;
- if (entry->flag & DELETE_BEHIND) {
- if (storeClientWaiting(entry)) {
- /* check if we want to defer reading */
- clen = entry->mem_obj->e_current_len;
- off = entry->mem_obj->e_lowest_offset;
- if ((clen - off) > FTP_DELETE_GAP) {
- debug(9, 3, "ftpReadReply: Read deferred for Object: %s\n",
- entry->url);
- debug(9, 3, "--> Current Gap: %d bytes\n", clen - off);
- /* reschedule, so it will automatically be reactivated when
- * Gap is big enough. */
- comm_set_select_handler(fd,
- COMM_SELECT_READ,
- (PF) ftpReadReply,
- (void *) data);
- /* dont try reading again for a while */
- comm_set_stall(fd, getStallDelay());
- return 0;
- }
- } else {
- /* we can terminate connection right now */
- squid_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL);
+ if (entry->flag & DELETE_BEHIND && !storeClientWaiting(entry)) {
+ /* we can terminate connection right now */
+ squid_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL);
+ comm_close(fd);
+ return 0;
+ }
+ /* check if we want to defer reading */
+ clen = entry->mem_obj->e_current_len;
+ off = storeGetLowestReaderOffset(entry);
+ if ((clen - off) > FTP_DELETE_GAP) {
+ if (entry->flag & CLIENT_ABORT_REQUEST) {
+ squid_error_entry(entry, ERR_CLIENT_ABORT, NULL);
comm_close(fd);
- return 0;
}
+ IOStats.Ftp.reads_deferred++;
+ debug(11, 3, "ftpReadReply: Read deferred for Object: %s\n",
+ entry->url);
+ debug(11, 3, " Current Gap: %d bytes\n", clen - off);
+ /* reschedule, so it will be automatically reactivated
+ * when Gap is big enough. */
+ comm_set_select_handler(fd,
+ COMM_SELECT_READ,
+ (PF) ftpReadReply,
+ (void *) data);
+ /* NOTE there is no read timeout handler to disable */
+ /* dont try reading again for a while */
+ comm_set_stall(fd, getStallDelay());
+ return 0;
}
errno = 0;
- len = read(fd, buf, READBUFSIZ);
+ IOStats.Ftp.reads++;
+ len = read(fd, buf, SQUID_TCP_SO_RCVBUF);
debug(9, 5, "ftpReadReply: FD %d, Read %d bytes\n", fd, len);
-
+ if (len > 0) {
+ for (clen = len - 1, bin = 0; clen; bin++)
+ clen >>= 1;
+ IOStats.Ftp.read_hist[bin]++;
+ }
if (len < 0) {
debug(9, 1, "ftpReadReply: read error: %s\n", xstrerror());
if (errno == EAGAIN || errno == EWOULDBLOCK) {
/* If we didn't see the magic marker, assume the transfer
* failed and arrange so the object gets ejected and
* never gets to disk. */
- debug(9, 1, "ftpReadReply: Didn't see magic marker, purging <URL:%s>.\n", entry->url);
+ debug(9, 1, "ftpReadReply: Purging '%s'\n", entry->url);
entry->expires = squid_curtime + getNegativeTTL();
BIT_RESET(entry->flag, CACHABLE);
storeReleaseRequest(entry);
char *buf;
int size;
int errflag;
- FtpData *data;
+ void *data;
{
+ FtpData *ftpState = (FtpData *) data;
StoreEntry *entry = NULL;
- entry = data->entry;
+ entry = ftpState->entry;
debug(9, 5, "ftpSendComplete: FD %d: size %d: errflag %d.\n",
fd, size, errflag);
put_free_8k_page(buf); /* Allocated by ftpSendRequest. */
buf = NULL;
}
- data->icp_page_ptr = NULL; /* So lifetime expire doesn't re-free */
- data->icp_rwd_ptr = NULL; /* Don't double free in lifetimeexpire */
+ ftpState->icp_page_ptr = NULL; /* So lifetime expire doesn't re-free */
if (errflag) {
squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
comm_close(fd);
return;
} else {
- comm_set_select_handler(data->ftp_fd,
+ comm_set_select_handler(ftpState->ftp_fd,
COMM_SELECT_READ,
(PF) ftpReadReply,
- (void *) data);
- comm_set_select_handler_plus_timeout(data->ftp_fd,
+ (void *) ftpState);
+ comm_set_select_handler_plus_timeout(ftpState->ftp_fd,
COMM_SELECT_TIMEOUT,
(PF) ftpLifetimeExpire,
- (void *) data, getReadTimeout());
+ (void *) ftpState, getReadTimeout());
}
}
mode = ftpBinary;
}
-#ifdef NO_NEED_TO_DO_THIS
- /* Remove leading slash from FTP url-path so that we can
- * handle ftp://user:pw@host/path objects where path and /path
- * are quite different. -DW */
- if (!strcmp(path, "/"))
- *path = '.';
- if (*path == '/')
- path++;
-#endif
-
/* Start building the buffer ... */
-
strcat(buf, getFtpProgram());
strcat(buf, space);
sprintf(tbuf, "-P %d ", data->request->port);
strcat(buf, tbuf);
}
+ if ((s = getVisibleHostname())) {
+ sprintf(tbuf, "-H %s ", s);
+ strcat(buf, tbuf);
+ }
strcat(buf, "-h "); /* httpify */
strcat(buf, "- "); /* stdout */
strcat(buf, data->request->host);
strcat(buf, *data->password ? data->password : "\"\"");
strcat(buf, "\n");
debug(9, 5, "ftpSendRequest: FD %d: buf '%s'\n", fd, buf);
- data->icp_rwd_ptr = icpWrite(fd,
+ comm_write(fd,
buf,
strlen(buf),
30,
debug(9, 5, "ftpConnInProgress: FD %d\n", fd);
- if (comm_connect(fd, localhost, CACHE_FTP_PORT) != COMM_OK) {
+ if (comm_connect(fd, localhost, ftpget_port) != COMM_OK) {
switch (errno) {
case EINPROGRESS:
case EALREADY:
debug(9, 3, "FtpStart: FD %d <URL:%s>\n", unusedfd, url);
- data = (FtpData *) xcalloc(1, sizeof(FtpData));
- data->entry = entry;
- data->request = request;
+ data = xcalloc(1, sizeof(FtpData));
+ storeLockObject(data->entry = entry, NULL, NULL);
+ data->request = requestLink(request);
/* Parse login info. */
ftp_login_parser(request->login, data);
unusedfd, data->request->host, data->request->urlpath,
data->user, data->password);
- data->ftp_fd = comm_open(COMM_NONBLOCKING, 0, 0, url);
+ data->ftp_fd = comm_open(COMM_NONBLOCKING,
+ local_addr,
+ 0,
+ url);
if (data->ftp_fd == COMM_ERROR) {
squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
- safe_free(data);
+ ftpStateFree(-1, data);
return COMM_ERROR;
}
/* Pipe/socket created ok */
/* register close handler */
- comm_set_select_handler(data->ftp_fd,
- COMM_SELECT_CLOSE,
+ comm_add_close_handler(data->ftp_fd,
(PF) ftpStateFree,
(void *) data);
/* Now connect ... */
- if ((status = comm_connect(data->ftp_fd, localhost, CACHE_FTP_PORT))) {
+ if ((status = comm_connect(data->ftp_fd, localhost, ftpget_port))) {
if (status != EINPROGRESS) {
squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
comm_close(data->ftp_fd);
return COMM_OK;
}
}
- fdstat_open(data->ftp_fd, Socket);
+ fdstat_open(data->ftp_fd, FD_SOCKET);
commSetNonBlocking(data->ftp_fd);
(void) fd_note(data->ftp_fd, entry->url);
void ftpServerClose()
{
- if (ftpget_server_pipe < 0)
+ /* NOTE: this function will be called repeatedly while shutdown is
+ * pending */
+ if (ftpget_server_read < 0)
return;
-
- comm_set_select_handler(ftpget_server_pipe,
- COMM_SELECT_EXCEPT,
+ comm_set_select_handler(ftpget_server_read,
+ COMM_SELECT_READ,
(PF) NULL,
(void *) NULL);
- fdstat_close(ftpget_server_pipe);
- close(ftpget_server_pipe);
- ftpget_server_pipe = -1;
+ fdstat_close(ftpget_server_read);
+ close(ftpget_server_read);
+ fdstat_close(ftpget_server_write);
+ close(ftpget_server_write);
+ ftpget_server_read = -1;
+ ftpget_server_write = -1;
}
int ftpInitialize()
{
int pid;
- int fd;
- int p[2];
- char pbuf[128];
+ int cfd;
+ int squid_to_ftpget[2];
+ int ftpget_to_squid[2];
+ static char pbuf[128];
char *ftpget = getFtpProgram();
+ struct sockaddr_in S;
+ int len;
- if (pipe(p) < 0) {
+ if (pipe(squid_to_ftpget) < 0) {
debug(9, 0, "ftpInitialize: pipe: %s\n", xstrerror());
return -1;
}
+ if (pipe(ftpget_to_squid) < 0) {
+ debug(9, 0, "ftpInitialize: pipe: %s\n", xstrerror());
+ return -1;
+ }
+ cfd = comm_open(COMM_NOCLOEXEC,
+ local_addr,
+ 0,
+ "ftpget -S socket");
+ if (cfd == COMM_ERROR) {
+ debug(9, 0, "ftpInitialize: Failed to create socket\n");
+ return -1;
+ }
+ len = sizeof(S);
+ memset(&S, '\0', len);
+ if (getsockname(cfd, (struct sockaddr *) &S, &len) < 0) {
+ debug(9, 0, "ftpInitialize: getsockname: %s\n", xstrerror());
+ comm_close(cfd);
+ return -1;
+ }
+ ftpget_port = ntohs(S.sin_port);
+ listen(cfd, FD_SETSIZE >> 2);
if ((pid = fork()) < 0) {
debug(9, 0, "ftpInitialize: fork: %s\n", xstrerror());
+ comm_close(cfd);
return -1;
}
if (pid != 0) { /* parent */
- close(p[0]);
- fdstat_open(p[1], Pipe);
- fd_note(p[1], "ftpget -S");
- fcntl(p[1], F_SETFD, 1); /* set close-on-exec */
+ comm_close(cfd);
+ close(squid_to_ftpget[0]);
+ close(ftpget_to_squid[1]);
+ fdstat_open(squid_to_ftpget[1], FD_PIPE);
+ fdstat_open(ftpget_to_squid[0], FD_PIPE);
+ fd_note(squid_to_ftpget[1], "ftpget -S");
+ fd_note(ftpget_to_squid[0], "ftpget -S");
+ fcntl(squid_to_ftpget[1], F_SETFD, 1); /* set close-on-exec */
+ fcntl(ftpget_to_squid[0], F_SETFD, 1); /* set close-on-exec */
/* if ftpget -S goes away, this handler should get called */
- comm_set_select_handler(p[1],
- COMM_SELECT_EXCEPT,
+ comm_set_select_handler(ftpget_to_squid[0],
+ COMM_SELECT_READ,
(PF) ftpServerClosed,
(void *) NULL);
- ftpget_server_pipe = p[1];
+ ftpget_server_write = squid_to_ftpget[1];
+ ftpget_server_read = ftpget_to_squid[0];
return 0;
}
/* child */
/* give up all extra priviligies */
no_suid();
/* set up stdin,stdout */
- dup2(p[0], 0);
+ dup2(squid_to_ftpget[0], 0);
+ dup2(ftpget_to_squid[1], 1);
dup2(fileno(debug_log), 2);
- close(p[0]);
- close(p[1]);
+ close(squid_to_ftpget[0]);
+ close(squid_to_ftpget[1]);
+ close(ftpget_to_squid[0]);
+ close(ftpget_to_squid[1]);
+ dup2(cfd, 3); /* pass listening socket to ftpget */
/* inherit stdin,stdout,stderr */
- for (fd = 3; fd < fdstat_biggest_fd(); fd++)
- (void) close(fd);
- sprintf(pbuf, "%d", CACHE_FTP_PORT);
+ for (cfd = 4; cfd <= fdstat_biggest_fd(); cfd++)
+ (void) close(cfd);
+ sprintf(pbuf, "%d", ftpget_port);
execlp(ftpget, ftpget, "-S", pbuf, NULL);
debug(9, 0, "ftpInitialize: %s: %s\n", ftpget, xstrerror());
_exit(1);
-/* $Id: gopher.cc,v 1.30 1996/05/03 22:56:27 wessels Exp $ */
+/*
+ * $Id: gopher.cc,v 1.31 1996/07/09 03:41:26 wessels Exp $
+ *
+ * DEBUG: section 10 Gopher
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
/*
- * DEBUG: Section 10 gopher: GOPHER
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
int len;
char *buf; /* pts to a 4k page */
char *icp_page_ptr; /* Pts to gopherStart buffer that needs to be freed */
- char *icp_rwd_ptr; /* Pts to icp rw structure that needs to be freed */
} GopherData;
GopherData *CreateGopherData();
{
if (gopherState == NULL)
return 1;
+ if (gopherState->entry)
+ storeUnlockObject(gopherState->entry);
put_free_4k_page(gopherState->buf);
xfree(gopherState);
return 0;
entry->url);
len = TEMP_BUF_SIZE - data->len;
}
- memcpy(data->buf + data->len, inbuf, len);
+ xmemcpy(data->buf + data->len, inbuf, len);
data->len += len;
return;
}
len = TEMP_BUF_SIZE;
}
if (len > (pos - inbuf)) {
- memcpy(data->buf, pos, len - (pos - inbuf));
+ xmemcpy(data->buf, pos, len - (pos - inbuf));
data->len = len - (pos - inbuf);
}
break;
int t;
int code;
int recno;
- char result[MAX_CSO_RESULT];
+ static char result[MAX_CSO_RESULT];
tline = line;
squid_error_entry(entry, ERR_READ_TIMEOUT, NULL);
if (data->icp_page_ptr)
put_free_4k_page(data->icp_page_ptr);
- if (data->icp_rwd_ptr)
- safe_free(data->icp_rwd_ptr);
comm_close(fd);
return 0;
}
squid_error_entry(entry, ERR_LIFETIME_EXP, NULL);
if (data->icp_page_ptr)
put_free_4k_page(data->icp_page_ptr);
- if (data->icp_rwd_ptr)
- safe_free(data->icp_rwd_ptr);
comm_set_select_handler(fd,
COMM_SELECT_READ | COMM_SELECT_WRITE,
0,
char *buf;
int size;
int errflag;
- GopherData *data;
+ void *data;
{
+ GopherData *gopherState = (GopherData *) data;
StoreEntry *entry = NULL;
- entry = data->entry;
+ entry = gopherState->entry;
debug(10, 5, "gopherSendComplete: FD %d size: %d errflag: %d\n",
fd, size, errflag);
if (errflag) {
* OK. We successfully reach remote site. Start MIME typing
* stuff. Do it anyway even though request is not HTML type.
*/
- gopherMimeCreate(data);
+ gopherMimeCreate(gopherState);
if (!BIT_TEST(entry->flag, ENTRY_HTML))
- data->conversion = NORMAL;
+ gopherState->conversion = NORMAL;
else
- switch (data->type_id) {
+ switch (gopherState->type_id) {
case GOPHER_DIRECTORY:
/* we got to convert it first */
BIT_SET(entry->flag, DELAY_SENDING);
- data->conversion = HTML_DIR;
- data->HTML_header_added = 0;
+ gopherState->conversion = HTML_DIR;
+ gopherState->HTML_header_added = 0;
break;
case GOPHER_INDEX:
/* we got to convert it first */
BIT_SET(entry->flag, DELAY_SENDING);
- data->conversion = HTML_INDEX_RESULT;
- data->HTML_header_added = 0;
+ gopherState->conversion = HTML_INDEX_RESULT;
+ gopherState->HTML_header_added = 0;
break;
case GOPHER_CSO:
/* we got to convert it first */
BIT_SET(entry->flag, DELAY_SENDING);
- data->conversion = HTML_CSO_RESULT;
- data->cso_recno = 0;
- data->HTML_header_added = 0;
+ gopherState->conversion = HTML_CSO_RESULT;
+ gopherState->cso_recno = 0;
+ gopherState->HTML_header_added = 0;
break;
default:
- data->conversion = NORMAL;
+ gopherState->conversion = NORMAL;
}
/* Schedule read reply. */
comm_set_select_handler(fd,
COMM_SELECT_READ,
(PF) gopherReadReply,
- (void *) data);
+ (void *) gopherState);
comm_set_select_handler_plus_timeout(fd,
COMM_SELECT_TIMEOUT,
(PF) gopherReadReplyTimeout,
- (void *) data,
+ (void *) gopherState,
getReadTimeout());
- comm_set_fd_lifetime(fd, -1); /* disable */
+ comm_set_fd_lifetime(fd, 86400); /* extend lifetime */
if (buf)
put_free_4k_page(buf); /* Allocated by gopherSendRequest. */
- data->icp_page_ptr = NULL;
- data->icp_rwd_ptr = NULL;
+ gopherState->icp_page_ptr = NULL;
}
/* This will be called when connect completes. Write request. */
}
debug(10, 5, "gopherSendRequest: FD %d\n", fd);
- data->icp_rwd_ptr = icpWrite(fd,
+ comm_write(fd,
buf,
len,
30,
int sock, status;
GopherData *data = CreateGopherData();
- data->entry = entry;
+ storeLockObject(data->entry = entry, NULL, NULL);
debug(10, 3, "gopherStart: url: %s\n", url);
return COMM_ERROR;
}
/* Create socket. */
- sock = comm_open(COMM_NONBLOCKING, 0, 0, url);
+ sock = comm_open(COMM_NONBLOCKING, getTcpOutgoingAddr(), 0, url);
if (sock == COMM_ERROR) {
debug(10, 4, "gopherStart: Failed because we're out of sockets.\n");
squid_error_entry(entry, ERR_NO_FDS, xstrerror());
gopherStateFree(-1, data);
return COMM_ERROR;
}
- comm_set_select_handler(sock,
- COMM_SELECT_CLOSE,
+ comm_add_close_handler(sock,
(PF) gopherStateFree,
(void *) data);
/* check if IP is already in cache. It must be.
* It should be done before this route is called.
* Otherwise, we cannot check return code for connect. */
- if (!ipcache_gethostbyname(data->host)) {
+ if (!ipcache_gethostbyname(data->host, 0)) {
debug(10, 4, "gopherStart: Called without IP entry in ipcache. OR lookup failed.\n");
squid_error_entry(entry, ERR_DNS_FAIL, dns_error_message);
comm_close(sock);
GopherData *CreateGopherData()
{
- GopherData *gd = (GopherData *) xcalloc(1, sizeof(GopherData));
+ GopherData *gd = xcalloc(1, sizeof(GopherData));
gd->buf = get_free_4k_page();
return (gd);
}
-/* $Id: http.cc,v 1.58 1996/05/03 22:56:27 wessels Exp $ */
+/*
+ * $Id: http.cc,v 1.59 1996/07/09 03:41:28 wessels Exp $
+ *
+ * DEBUG: section 11 Hypertext Transfer Protocol (HTTP)
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
/*
- * DEBUG: Section 11 http: HTTP
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
-#define READBUFSIZ (1<<14)
#define HTTP_DELETE_GAP (1<<18)
-typedef struct _httpdata {
- StoreEntry *entry;
- request_t *request;
- char *req_hdr;
- char *icp_page_ptr; /* Used to send proxy-http request:
- * put_free_8k_page(me) if the lifetime
- * expires */
- char *icp_rwd_ptr; /* When a lifetime expires during the
- * middle of an icpwrite, don't lose the
- * icpReadWriteData */
- char *reply_hdr;
- int reply_hdr_state;
- int free_request;
-} HttpData;
+struct {
+ int parsed;
+ int date;
+ int lm;
+ int exp;
+ int clen;
+ int ctype;
+} ReplyHeaderStats;
static int httpStateFree(fd, httpState)
int fd;
- HttpData *httpState;
+ HttpStateData *httpState;
{
if (httpState == NULL)
return 1;
+ storeUnlockObject(httpState->entry);
if (httpState->reply_hdr) {
put_free_8k_page(httpState->reply_hdr);
httpState->reply_hdr = NULL;
}
- if (httpState->icp_page_ptr) {
- put_free_8k_page(httpState->icp_page_ptr);
- httpState->icp_page_ptr = NULL;
+ if (httpState->reqbuf && httpState->buf_type == BUF_TYPE_8K) {
+ put_free_8k_page(httpState->reqbuf);
+ httpState->reqbuf = NULL;
+ } else {
+ safe_free(httpState->reqbuf)
}
- if (httpState->icp_rwd_ptr)
- safe_free(httpState->icp_rwd_ptr);
- if (httpState->free_request)
- safe_free(httpState->request);
+ requestUnlink(httpState->request);
xfree(httpState);
return 0;
}
}
/* This will be called when timeout on read. */
-static void httpReadReplyTimeout(fd, data)
+static void httpReadReplyTimeout(fd, httpState)
int fd;
- HttpData *data;
+ HttpStateData *httpState;
{
StoreEntry *entry = NULL;
- entry = data->entry;
+ entry = httpState->entry;
debug(11, 4, "httpReadReplyTimeout: FD %d: <URL:%s>\n", fd, entry->url);
squid_error_entry(entry, ERR_READ_TIMEOUT, NULL);
comm_set_select_handler(fd, COMM_SELECT_READ, 0, 0);
}
/* This will be called when socket lifetime is expired. */
-static void httpLifetimeExpire(fd, data)
+static void httpLifetimeExpire(fd, httpState)
int fd;
- HttpData *data;
+ HttpStateData *httpState;
{
StoreEntry *entry = NULL;
- entry = data->entry;
+ entry = httpState->entry;
debug(11, 4, "httpLifeTimeExpire: FD %d: <URL:%s>\n", fd, entry->url);
squid_error_entry(entry, ERR_LIFETIME_EXP, NULL);
comm_close(fd);
}
+/* This object can be cached for a long time */
+static void httpMakePublic(entry)
+ StoreEntry *entry;
+{
+ entry->expires = squid_curtime + ttlSet(entry);
+ if (BIT_TEST(entry->flag, CACHABLE))
+ storeSetPublicKey(entry);
+}
+
+/* This object should never be cached at all */
+static void httpMakePrivate(entry)
+ StoreEntry *entry;
+{
+ storeSetPrivateKey(entry);
+ storeExpireNow(entry);
+ BIT_RESET(entry->flag, CACHABLE);
+ storeReleaseRequest(entry); /* delete object when not used */
+}
+
+/* This object may be negatively cached */
+static void httpCacheNegatively(entry)
+ StoreEntry *entry;
+{
+ entry->expires = squid_curtime + getNegativeTTL();
+ if (BIT_TEST(entry->flag, CACHABLE))
+ storeSetPublicKey(entry);
+ /* XXX: mark object "not to store on disk"? */
+}
+
+
+/* Build a reply structure from HTTP reply headers */
+void httpParseHeaders(buf, reply)
+ char *buf;
+ struct _http_reply *reply;
+{
+ char *headers = NULL;
+ char *t = NULL;
+ char *s = NULL;
+
+ ReplyHeaderStats.parsed++;
+ headers = xstrdup(buf);
+ t = strtok(headers, "\n");
+ while (t) {
+ s = t + strlen(t);
+ while (*s == '\r')
+ *s-- = '\0';
+ if (!strncasecmp(t, "HTTP", 4)) {
+ sscanf(t + 1, "%lf", &reply->version);
+ if ((t = strchr(t, ' '))) {
+ t++;
+ reply->code = atoi(t);
+ }
+ } else if (!strncasecmp(t, "Content-type:", 13)) {
+ if ((t = strchr(t, ' '))) {
+ t++;
+ strncpy(reply->content_type, t, HTTP_REPLY_FIELD_SZ - 1);
+ ReplyHeaderStats.ctype++;
+ }
+ } else if (!strncasecmp(t, "Content-length:", 15)) {
+ if ((t = strchr(t, ' '))) {
+ t++;
+ reply->content_length = atoi(t);
+ ReplyHeaderStats.clen++;
+ }
+ } else if (!strncasecmp(t, "Date:", 5)) {
+ if ((t = strchr(t, ' '))) {
+ t++;
+ strncpy(reply->date, t, HTTP_REPLY_FIELD_SZ - 1);
+ ReplyHeaderStats.date++;
+ }
+ } else if (!strncasecmp(t, "Expires:", 8)) {
+ if ((t = strchr(t, ' '))) {
+ t++;
+ strncpy(reply->expires, t, HTTP_REPLY_FIELD_SZ - 1);
+ ReplyHeaderStats.exp++;
+ }
+ } else if (!strncasecmp(t, "Last-Modified:", 14)) {
+ if ((t = strchr(t, ' '))) {
+ t++;
+ strncpy(reply->last_modified, t, HTTP_REPLY_FIELD_SZ - 1);
+ ReplyHeaderStats.lm++;
+ }
+ }
+ t = strtok(NULL, "\n");
+ }
+ safe_free(headers);
+}
+
-static void httpProcessReplyHeader(data, buf, size)
- HttpData *data;
+void httpProcessReplyHeader(httpState, buf, size)
+ HttpStateData *httpState;
char *buf; /* chunk just read by httpReadReply() */
int size;
{
- char *s = NULL;
char *t = NULL;
- char *t1 = NULL;
- char *t2 = NULL;
- StoreEntry *entry = data->entry;
- char *headers = NULL;
+ StoreEntry *entry = httpState->entry;
int room;
int hdr_len;
struct _http_reply *reply = NULL;
debug(11, 3, "httpProcessReplyHeader: key '%s'\n", entry->key);
- if (data->reply_hdr == NULL) {
- data->reply_hdr = get_free_8k_page();
- memset(data->reply_hdr, '\0', 8192);
+ if (httpState->reply_hdr == NULL) {
+ httpState->reply_hdr = get_free_8k_page();
+ memset(httpState->reply_hdr, '\0', 8192);
}
- if (data->reply_hdr_state == 0) {
- hdr_len = strlen(data->reply_hdr);
+ if (httpState->reply_hdr_state == 0) {
+ hdr_len = strlen(httpState->reply_hdr);
room = 8191 - hdr_len;
- strncat(data->reply_hdr, buf, room < size ? room : size);
+ strncat(httpState->reply_hdr, buf, room < size ? room : size);
hdr_len += room < size ? room : size;
- if (hdr_len > 4 && strncmp(data->reply_hdr, "HTTP/", 5)) {
+ if (hdr_len > 4 && strncmp(httpState->reply_hdr, "HTTP/", 5)) {
debug(11, 3, "httpProcessReplyHeader: Non-HTTP-compliant header: '%s'\n", entry->key);
- data->reply_hdr_state += 2;
+ httpState->reply_hdr_state += 2;
return;
}
- /* need to take the lowest, non-zero pointer to the end of the headers.
- * some objects have \n\n separating header and body, but \r\n\r\n in
- * body text. */
- t1 = strstr(data->reply_hdr, "\r\n\r\n");
- t2 = strstr(data->reply_hdr, "\n\n");
- if (t1 && t2)
- t = t2 < t1 ? t2 : t1;
- else
- t = t2 ? t2 : t1;
+ /* Find the end of the headers */
+ t = mime_headers_end(httpState->reply_hdr);
if (!t)
+ /* XXX: Here we could check for buffer overflow... */
return; /* headers not complete */
- t += (t == t1 ? 4 : 2);
+ /* Cut after end of headers */
*t = '\0';
reply = entry->mem_obj->reply;
- reply->hdr_sz = t - data->reply_hdr;
+ reply->hdr_sz = t - httpState->reply_hdr;
debug(11, 7, "httpProcessReplyHeader: hdr_sz = %d\n", reply->hdr_sz);
- data->reply_hdr_state++;
+ httpState->reply_hdr_state++;
}
- if (data->reply_hdr_state == 1) {
- headers = xstrdup(data->reply_hdr);
- data->reply_hdr_state++;
+ if (httpState->reply_hdr_state == 1) {
+ httpState->reply_hdr_state++;
debug(11, 9, "GOT HTTP REPLY HDR:\n---------\n%s\n----------\n",
- data->reply_hdr);
- t = strtok(headers, "\n");
- while (t) {
- s = t + strlen(t);
- while (*s == '\r')
- *s-- = '\0';
- if (!strncasecmp(t, "HTTP", 4)) {
- sscanf(t + 1, "%lf", &reply->version);
- if ((t = strchr(t, ' '))) {
- t++;
- reply->code = atoi(t);
- }
- } else if (!strncasecmp(t, "Content-type:", 13)) {
- if ((t = strchr(t, ' '))) {
- t++;
- strncpy(reply->content_type, t, HTTP_REPLY_FIELD_SZ - 1);
- }
- } else if (!strncasecmp(t, "Content-length:", 15)) {
- if ((t = strchr(t, ' '))) {
- t++;
- reply->content_length = atoi(t);
- }
- } else if (!strncasecmp(t, "Date:", 5)) {
- if ((t = strchr(t, ' '))) {
- t++;
- strncpy(reply->date, t, HTTP_REPLY_FIELD_SZ - 1);
- }
- } else if (!strncasecmp(t, "Expires:", 8)) {
- if ((t = strchr(t, ' '))) {
- t++;
- strncpy(reply->expires, t, HTTP_REPLY_FIELD_SZ - 1);
- }
- } else if (!strncasecmp(t, "Last-Modified:", 14)) {
- if ((t = strchr(t, ' '))) {
- t++;
- strncpy(reply->last_modified, t, HTTP_REPLY_FIELD_SZ - 1);
- }
- }
- t = strtok(NULL, "\n");
- }
- safe_free(headers);
+ httpState->reply_hdr);
+ /* Parse headers into reply structure */
+ httpParseHeaders(httpState->reply_hdr, reply);
+ /* Check if object is cacheable or not based on reply code */
if (reply->code)
debug(11, 3, "httpProcessReplyHeader: HTTP CODE: %d\n", reply->code);
switch (reply->code) {
+ /* Responses that are cacheable */
case 200: /* OK */
case 203: /* Non-Authoritative Information */
case 300: /* Multiple Choices */
case 301: /* Moved Permanently */
case 410: /* Gone */
- /* These can be cached for a long time, make the key public */
- entry->expires = squid_curtime + ttlSet(entry);
- if (BIT_TEST(entry->flag, CACHABLE))
- storeSetPublicKey(entry);
+ /* don't cache objects from neighbors w/o LMT, Date, or Expires */
+ if (*reply->date)
+ httpMakePublic(entry);
+ else if (*reply->last_modified)
+ httpMakePublic(entry);
+ else if (!httpState->neighbor)
+ httpMakePublic(entry);
+ else if (*reply->expires)
+ httpMakePublic(entry);
+ else
+ httpMakePrivate(entry);
+ break;
+ /* Responses that only are cacheable if the server says so */
+ case 302: /* Moved temporarily */
+ if (*reply->expires)
+ httpMakePublic(entry);
+ else
+ httpMakePrivate(entry);
break;
+ /* Errors can be negatively cached */
+ case 204: /* No Content */
+ case 305: /* Use Proxy (proxy redirect) */
+ case 400: /* Bad Request */
+ case 403: /* Forbidden */
+ case 404: /* Not Found */
+ case 405: /* Method Now Allowed */
+ case 414: /* Request-URI Too Long */
+ case 500: /* Internal Server Error */
+ case 501: /* Not Implemented */
+ case 502: /* Bad Gateway */
+ case 503: /* Service Unavailable */
+ case 504: /* Gateway Timeout */
+ if (*reply->expires)
+ httpMakePublic(entry);
+ else
+ httpCacheNegatively(entry);
+ break;
+ /* Some responses can never be cached */
+ case 303: /* See Other */
case 304: /* Not Modified */
case 401: /* Unauthorized */
case 407: /* Proxy Authentication Required */
- /* These should never be cached at all */
- storeSetPrivateKey(entry);
- storeExpireNow(entry);
- BIT_RESET(entry->flag, CACHABLE);
- storeReleaseRequest(entry);
- break;
- default:
- /* These can be negative cached, make key public */
- entry->expires = squid_curtime + getNegativeTTL();
- if (BIT_TEST(entry->flag, CACHABLE))
- storeSetPublicKey(entry);
+ default: /* Unknown status code */
+ httpMakePrivate(entry);
break;
}
}
/* This will be called when data is ready to be read from fd. Read until
* error or connection closed. */
/* XXX this function is too long! */
-static void httpReadReply(fd, data)
+static void httpReadReply(fd, httpState)
int fd;
- HttpData *data;
+ HttpStateData *httpState;
{
- static char buf[READBUFSIZ];
+ static char buf[SQUID_TCP_SO_RCVBUF];
int len;
+ int bin;
int clen;
int off;
StoreEntry *entry = NULL;
- entry = data->entry;
+ entry = httpState->entry;
if (entry->flag & DELETE_BEHIND && !storeClientWaiting(entry)) {
/* we can terminate connection right now */
squid_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL);
clen = entry->mem_obj->e_current_len;
off = storeGetLowestReaderOffset(entry);
if ((clen - off) > HTTP_DELETE_GAP) {
+ if (entry->flag & CLIENT_ABORT_REQUEST) {
+ squid_error_entry(entry, ERR_CLIENT_ABORT, NULL);
+ comm_close(fd);
+ return;
+ }
+ IOStats.Http.reads_deferred++;
debug(11, 3, "httpReadReply: Read deferred for Object: %s\n",
entry->url);
debug(11, 3, " Current Gap: %d bytes\n", clen - off);
comm_set_select_handler(fd,
COMM_SELECT_READ,
(PF) httpReadReply,
- (void *) data);
- /* don't install read timeout until we are below the GAP */
+ (void *) httpState);
+ /* disable read timeout until we are below the GAP */
comm_set_select_handler_plus_timeout(fd,
COMM_SELECT_TIMEOUT,
(PF) NULL,
(void *) NULL,
(time_t) 0);
+ comm_set_fd_lifetime(fd, 3600); /* limit during deferring */
/* dont try reading again for a while */
comm_set_stall(fd, getStallDelay());
return;
}
errno = 0;
- len = read(fd, buf, READBUFSIZ);
+ IOStats.Http.reads++;
+ len = read(fd, buf, SQUID_TCP_SO_RCVBUF);
debug(11, 5, "httpReadReply: FD %d: len %d.\n", fd, len);
-
+ comm_set_fd_lifetime(fd, 86400); /* extend after good read */
+ if (len > 0) {
+ for (clen = len - 1, bin = 0; clen; bin++)
+ clen >>= 1;
+ IOStats.Http.read_hist[bin]++;
+ }
if (len < 0) {
debug(11, 2, "httpReadReply: FD %d: read failure: %s.\n",
fd, xstrerror());
/* reinstall handlers */
/* XXX This may loop forever */
comm_set_select_handler(fd, COMM_SELECT_READ,
- (PF) httpReadReply, (void *) data);
+ (PF) httpReadReply, (void *) httpState);
comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT,
- (PF) httpReadReplyTimeout, (void *) data, getReadTimeout());
+ (PF) httpReadReplyTimeout, (void *) httpState, getReadTimeout());
} else {
BIT_RESET(entry->flag, CACHABLE);
storeReleaseRequest(entry);
comm_set_select_handler(fd,
COMM_SELECT_READ,
(PF) httpReadReply,
- (void *) data);
+ (void *) httpState);
comm_set_select_handler_plus_timeout(fd,
COMM_SELECT_TIMEOUT,
(PF) httpReadReplyTimeout,
- (void *) data, getReadTimeout());
+ (void *) httpState, getReadTimeout());
} else if (entry->flag & CLIENT_ABORT_REQUEST) {
/* append the last bit of info we get */
storeAppend(entry, buf, len);
comm_close(fd);
} else {
storeAppend(entry, buf, len);
- if (data->reply_hdr_state < 2 && len > 0)
- httpProcessReplyHeader(data, buf, len);
+ if (httpState->reply_hdr_state < 2 && len > 0)
+ httpProcessReplyHeader(httpState, buf, len);
comm_set_select_handler(fd,
COMM_SELECT_READ,
(PF) httpReadReply,
- (void *) data);
+ (void *) httpState);
comm_set_select_handler_plus_timeout(fd,
COMM_SELECT_TIMEOUT,
(PF) httpReadReplyTimeout,
- (void *) data,
+ (void *) httpState,
getReadTimeout());
}
}
char *buf;
int size;
int errflag;
- HttpData *data;
+ void *data;
{
+ HttpStateData *httpState = data;
StoreEntry *entry = NULL;
- entry = data->entry;
+ entry = httpState->entry;
debug(11, 5, "httpSendComplete: FD %d: size %d: errflag %d.\n",
fd, size, errflag);
- if (buf) {
- put_free_8k_page(buf); /* Allocated by httpSendRequest. */
- buf = NULL;
+ if (httpState->reqbuf && httpState->buf_type == BUF_TYPE_8K) {
+ put_free_8k_page(httpState->reqbuf);
+ httpState->reqbuf = NULL;
+ } else {
+ safe_free(httpState->reqbuf);
}
- data->icp_page_ptr = NULL; /* So lifetime expire doesn't re-free */
- data->icp_rwd_ptr = NULL; /* Don't double free in lifetimeexpire */
if (errflag) {
squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
comm_set_select_handler(fd,
COMM_SELECT_READ,
(PF) httpReadReply,
- (void *) data);
+ (void *) httpState);
comm_set_select_handler_plus_timeout(fd,
COMM_SELECT_TIMEOUT,
(PF) httpReadReplyTimeout,
- (void *) data,
+ (void *) httpState,
getReadTimeout());
- comm_set_fd_lifetime(fd, -1); /* disable lifetime DPW */
+ comm_set_fd_lifetime(fd, 86400); /* extend lifetime */
}
}
/* This will be called when connect completes. Write request. */
-static void httpSendRequest(fd, data)
+static void httpSendRequest(fd, httpState)
int fd;
- HttpData *data;
+ HttpStateData *httpState;
{
char *xbuf = NULL;
char *ybuf = NULL;
int len = 0;
int buflen;
int cfd = -1;
- request_t *req = data->request;
+ request_t *req = httpState->request;
char *Method = RequestMethodStr[req->method];
- debug(11, 5, "httpSendRequest: FD %d: data %p.\n", fd, data);
+ debug(11, 5, "httpSendRequest: FD %d: httpState %p.\n", fd, httpState);
buflen = strlen(Method) + strlen(req->urlpath);
- if (data->req_hdr)
- buflen += strlen(data->req_hdr);
+ if (httpState->req_hdr)
+ buflen += strlen(httpState->req_hdr);
buflen += 512; /* lots of extra */
- if (req->method == METHOD_POST && data->req_hdr) {
- if ((t = strstr(data->req_hdr, "\r\n\r\n"))) {
- post_buf = xstrdup(t + 4);
- *(t + 4) = '\0';
+ if ((req->method == METHOD_POST || req->method == METHOD_PUT) && httpState->req_hdr) {
+ if ((t = mime_headers_end(httpState->req_hdr))) {
+ post_buf = xstrdup(t);
+ *t = '\0';
}
}
- /* Since we limit the URL read to a 4K page, I doubt that the
- * mime header could be longer than an 8K page */
- buf = (char *) get_free_8k_page();
- data->icp_page_ptr = buf;
- if (buflen > DISK_PAGE_SIZE) {
- debug(11, 0, "Mime header length %d is breaking ICP code\n", buflen);
+ if (buflen < DISK_PAGE_SIZE) {
+ httpState->reqbuf = get_free_8k_page();
+ memset(httpState->reqbuf, '\0', buflen);
+ httpState->buf_type = BUF_TYPE_8K;
+ } else {
+ httpState->reqbuf = xcalloc(buflen, 1);
+ httpState->buf_type = BUF_TYPE_MALLOC;
}
- memset(buf, '\0', buflen);
+ buf = httpState->reqbuf;
- sprintf(buf, "%s %s HTTP/1.0\r\n", Method, req->urlpath);
+ sprintf(buf, "%s %s HTTP/1.0\r\n",
+ Method,
+ *req->urlpath ? req->urlpath : "/");
len = strlen(buf);
- if (data->req_hdr) { /* we have to parse the request header */
- xbuf = xstrdup(data->req_hdr);
+ if (httpState->req_hdr) { /* we have to parse the request header */
+ xbuf = xstrdup(httpState->req_hdr);
for (t = strtok(xbuf, crlf); t; t = strtok(NULL, crlf)) {
if (strncasecmp(t, "User-Agent:", 11) == 0) {
ybuf = (char *) get_free_4k_page();
}
/* Add Forwarded: header */
ybuf = get_free_4k_page();
- if (data->entry->mem_obj)
- cfd = data->entry->mem_obj->fd_of_first_client;
+ if (httpState->entry->mem_obj)
+ cfd = httpState->entry->mem_obj->fd_of_first_client;
if (cfd < 0) {
- sprintf(ybuf, "Forwarded: by http://%s:%d/\r\n",
- getMyHostname(), getAsciiPortNum());
+ sprintf(ybuf, "%s\r\n", ForwardedBy);
} else {
- sprintf(ybuf, "Forwarded: by http://%s:%d/ for %s\r\n",
- getMyHostname(), getAsciiPortNum(), fd_table[cfd].ipaddr);
+ sprintf(ybuf, "%s for %s\r\n", ForwardedBy, fd_table[cfd].ipaddr);
}
strcat(buf, ybuf);
len += strlen(ybuf);
xfree(post_buf);
}
debug(11, 6, "httpSendRequest: FD %d: buf '%s'\n", fd, buf);
- data->icp_rwd_ptr = icpWrite(fd,
+ comm_write(fd,
buf,
len,
30,
httpSendComplete,
- (void *) data);
+ httpState);
}
-static void httpConnInProgress(fd, data)
+static void httpConnInProgress(fd, httpState)
int fd;
- HttpData *data;
+ HttpStateData *httpState;
{
- StoreEntry *entry = data->entry;
- request_t *req = data->request;
+ StoreEntry *entry = httpState->entry;
+ request_t *req = httpState->request;
- debug(11, 5, "httpConnInProgress: FD %d data=%p\n", fd, data);
+ debug(11, 5, "httpConnInProgress: FD %d httpState=%p\n", fd, httpState);
if (comm_connect(fd, req->host, req->port) != COMM_OK) {
debug(11, 5, "httpConnInProgress: FD %d: %s\n", fd, xstrerror());
comm_set_select_handler(fd,
COMM_SELECT_WRITE,
(PF) httpConnInProgress,
- (void *) data);
+ (void *) httpState);
return;
default:
squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
}
/* Call the real write handler, now that we're fully connected */
comm_set_select_handler(fd, COMM_SELECT_WRITE,
- (PF) httpSendRequest, (void *) data);
+ (PF) httpSendRequest, (void *) httpState);
}
int proxyhttpStart(e, url, entry)
{
int sock;
int status;
- HttpData *data = NULL;
+ HttpStateData *httpState = NULL;
request_t *request = NULL;
debug(11, 3, "proxyhttpStart: \"%s %s\"\n",
debug(11, 10, "proxyhttpStart: HTTP request header:\n%s\n",
entry->mem_obj->mime_hdr);
- if (e->proxy_only)
+ if (e->options & NEIGHBOR_PROXY_ONLY)
storeStartDeleteBehind(entry);
/* Create socket. */
- sock = comm_open(COMM_NONBLOCKING, 0, 0, url);
+ sock = comm_open(COMM_NONBLOCKING, getTcpOutgoingAddr(), 0, url);
if (sock == COMM_ERROR) {
debug(11, 4, "proxyhttpStart: Failed because we're out of sockets.\n");
squid_error_entry(entry, ERR_NO_FDS, xstrerror());
return COMM_ERROR;
}
- data = (HttpData *) xcalloc(1, sizeof(HttpData));
- data->entry = entry;
- data->req_hdr = entry->mem_obj->mime_hdr;
- request = (request_t *) xcalloc(1, sizeof(request_t));
- data->free_request = 1;
- data->request = request;
+ httpState = xcalloc(1, sizeof(HttpStateData));
+ storeLockObject(httpState->entry = entry, NULL, NULL);
+ httpState->req_hdr = entry->mem_obj->mime_hdr;
+ request = get_free_request_t();
+ httpState->request = requestLink(request);
+ httpState->neighbor = e;
/* register the handler to free HTTP state data when the FD closes */
- comm_set_select_handler(sock,
- COMM_SELECT_CLOSE,
+ comm_add_close_handler(sock,
(PF) httpStateFree,
- (void *) data);
+ (void *) httpState);
request->method = entry->method;
strncpy(request->host, e->host, SQUIDHOSTNAMELEN);
- request->port = e->ascii_port;
+ request->port = e->http_port;
strncpy(request->urlpath, url, MAX_URL);
/* check if IP is already in cache. It must be.
* It should be done before this route is called.
* Otherwise, we cannot check return code for connect. */
- if (!ipcache_gethostbyname(request->host)) {
+ if (!ipcache_gethostbyname(request->host, IP_BLOCKING_LOOKUP)) {
debug(11, 4, "proxyhttpstart: Called without IP entry in ipcache. OR lookup failed.\n");
squid_error_entry(entry, ERR_DNS_FAIL, dns_error_message);
comm_close(sock);
} else {
debug(11, 5, "proxyhttpStart: FD %d: EINPROGRESS.\n", sock);
comm_set_select_handler(sock, COMM_SELECT_LIFETIME,
- (PF) httpLifetimeExpire, (void *) data);
+ (PF) httpLifetimeExpire, (void *) httpState);
comm_set_select_handler(sock, COMM_SELECT_WRITE,
- (PF) httpConnInProgress, (void *) data);
+ (PF) httpConnInProgress, (void *) httpState);
return COMM_OK;
}
}
/* Install connection complete handler. */
fd_note(sock, entry->url);
comm_set_select_handler(sock, COMM_SELECT_LIFETIME,
- (PF) httpLifetimeExpire, (void *) data);
+ (PF) httpLifetimeExpire, (void *) httpState);
comm_set_select_handler(sock, COMM_SELECT_WRITE,
- (PF) httpSendRequest, (void *) data);
+ (PF) httpSendRequest, (void *) httpState);
return COMM_OK;
}
{
/* Create state structure. */
int sock, status;
- HttpData *data = NULL;
+ HttpStateData *httpState = NULL;
debug(11, 3, "httpStart: \"%s %s\"\n",
RequestMethodStr[request->method], url);
debug(11, 10, "httpStart: req_hdr '%s'\n", req_hdr);
/* Create socket. */
- sock = comm_open(COMM_NONBLOCKING, 0, 0, url);
+ sock = comm_open(COMM_NONBLOCKING, getTcpOutgoingAddr(), 0, url);
if (sock == COMM_ERROR) {
debug(11, 4, "httpStart: Failed because we're out of sockets.\n");
squid_error_entry(entry, ERR_NO_FDS, xstrerror());
return COMM_ERROR;
}
- data = (HttpData *) xcalloc(1, sizeof(HttpData));
- data->entry = entry;
- data->req_hdr = req_hdr;
- data->request = request;
- comm_set_select_handler(sock,
- COMM_SELECT_CLOSE,
+ httpState = xcalloc(1, sizeof(HttpStateData));
+ storeLockObject(httpState->entry = entry, NULL, NULL);
+ httpState->req_hdr = req_hdr;
+ httpState->request = requestLink(request);
+ comm_add_close_handler(sock,
(PF) httpStateFree,
- (void *) data);
+ (void *) httpState);
/* check if IP is already in cache. It must be.
* It should be done before this route is called.
* Otherwise, we cannot check return code for connect. */
- if (!ipcache_gethostbyname(request->host)) {
+ if (!ipcache_gethostbyname(request->host, 0)) {
debug(11, 4, "httpstart: Called without IP entry in ipcache. OR lookup failed.\n");
squid_error_entry(entry, ERR_DNS_FAIL, dns_error_message);
comm_close(sock);
} else {
debug(11, 5, "httpStart: FD %d: EINPROGRESS.\n", sock);
comm_set_select_handler(sock, COMM_SELECT_LIFETIME,
- (PF) httpLifetimeExpire, (void *) data);
+ (PF) httpLifetimeExpire, (void *) httpState);
comm_set_select_handler(sock, COMM_SELECT_WRITE,
- (PF) httpConnInProgress, (void *) data);
+ (PF) httpConnInProgress, (void *) httpState);
return COMM_OK;
}
}
/* Install connection complete handler. */
fd_note(sock, entry->url);
comm_set_select_handler(sock, COMM_SELECT_LIFETIME,
- (PF) httpLifetimeExpire, (void *) data);
+ (PF) httpLifetimeExpire, (void *) httpState);
comm_set_select_handler(sock, COMM_SELECT_WRITE,
- (PF) httpSendRequest, (void *) data);
+ (PF) httpSendRequest, (void *) httpState);
return COMM_OK;
}
+
+void httpReplyHeaderStats(entry)
+ StoreEntry *entry;
+{
+ storeAppendPrintf(entry, open_bracket);
+ storeAppendPrintf(entry, "{HTTP Reply Headers}\n");
+ storeAppendPrintf(entry, "{Headers parsed: %d}\n",
+ ReplyHeaderStats.parsed);
+ storeAppendPrintf(entry, "{ Date: %d}\n",
+ ReplyHeaderStats.date);
+ storeAppendPrintf(entry, "{ Last-Modified: %d}\n",
+ ReplyHeaderStats.lm);
+ storeAppendPrintf(entry, "{ Expires: %d}\n",
+ ReplyHeaderStats.exp);
+ storeAppendPrintf(entry, "{ Content-Type: %d}\n",
+ ReplyHeaderStats.ctype);
+ storeAppendPrintf(entry, "{Content-Length: %d}\n",
+ ReplyHeaderStats.clen);
+ storeAppendPrintf(entry, close_bracket);
+}
-/* $Id: ident.cc,v 1.1 1996/05/03 23:22:22 wessels Exp $ */
+/* $Id: ident.cc,v 1.2 1996/07/09 03:41:31 wessels Exp $ */
/*
* DEBUG: Section 30 ident/RFC931
#define IDENT_PORT 113
-static void identRequestComplete _PARAMS((int, char *, int, int, icpStateData *));
+static void identRequestComplete _PARAMS((int, char *, int, int, void *));
static void identReadReply _PARAMS((int, icpStateData *));
static void identClose _PARAMS((int, icpStateData *));
debug(30, 1, "identStart: peer is %s:%d\n", host, port);
if (sock < 0) {
- if ((sock = comm_open(COMM_NONBLOCKING, 0, 0, "ident")) == COMM_ERROR) {
- debug(30, 4, "identStart: Failed because we're out of sockets.\n");
+ sock = comm_open(COMM_NONBLOCKING, getTcpOutgoingAddr(), 0, "ident");
+ if (sock == COMM_ERROR)
return;
- }
}
icpState->ident_fd = sock;
- comm_set_select_handler(sock,
- COMM_SELECT_CLOSE,
+ comm_add_close_handler(sock,
(PF) identClose,
(void *) icpState);
if ((status = comm_connect(sock, host, IDENT_PORT)) < 0) {
sprintf(reqbuf, "%d, %d\r\n",
ntohs(icpState->peer.sin_port),
ntohs(icpState->me.sin_port));
- /* XXX icpWrite() returns a data structure which we need to free if there is
- * a timeout */
- (void) icpWrite(sock,
+ (void) comm_write(sock,
reqbuf,
strlen(reqbuf),
5, /* timeout */
(void *) icpState);
}
-static void identRequestComplete(fd, buf, size, errflag, state)
+static void identRequestComplete(fd, buf, size, errflag, data)
int fd;
char *buf;
int size;
int errflag;
- icpStateData *state;
+ void *data;
{
debug(30, 1, "identRequestComplete: FD %d: wrote %d bytes\n", fd, size);
}
-/* $Id: ipcache.cc,v 1.28 1996/05/03 22:56:29 wessels Exp $ */
+/*
+ * $Id: ipcache.cc,v 1.29 1996/07/09 03:41:31 wessels Exp $
+ *
+ * DEBUG: section 14 IP Cache
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
/*
- * DEBUG: Section 14 ipcache: IP Cache
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
-
#define MAX_LINELEN (4096)
-char ipcache_status_char _PARAMS((ipcache_entry *));
-int ipcache_hash_entry_count();
#define MAX_IP 1024 /* Maximum cached IP */
-#define IP_LOW_WATER 70
-#define IP_HIGH_WATER 90
+#define IP_LOW_WATER 90
+#define IP_HIGH_WATER 95
#define MAX_HOST_NAME 256
-#define IP_INBUF 4096
+#define IP_INBUF_SZ 4096
-long ipcache_low = 180;
-long ipcache_high = 200;
-
-typedef struct _ip_pending {
+struct _ip_pending {
int fd;
IPH handler;
- void *data;
+ void *handlerData;
struct _ip_pending *next;
-} IpPending;
-
+};
-typedef struct _ipcache_list {
- ipcache_entry *entry;
- struct _ipcache_list *next;
-} ipcache_list;
+#define DNS_FLAG_ALIVE 0x01
+#define DNS_FLAG_BUSY 0x02
+#define DNS_FLAG_CLOSING 0x04
-
-typedef struct _dnsserver_entry {
+typedef struct _dnsserver {
int id;
- int alive;
+ int flags;
int inpipe;
int outpipe;
- int pending_count; /* counter of outstanding request */
- long lastcall;
- long answer;
+ time_t lastcall;
+ time_t answer;
unsigned int offset;
unsigned int size;
char *ip_inbuf;
- /* global ipcache_entry list for pending entry */
- ipcache_list *global_pending;
- ipcache_list *global_pending_tail;
-} dnsserver_entry;
+ struct timeval dispatch_time;
+ ipcache_entry *ip_entry;
+} dnsserver_t;
+
+static struct {
+ int requests;
+ int hits;
+ int misses;
+ int pending_hits;
+ int negative_hits;
+ int dnsserver_requests;
+ int dnsserver_replies;
+ int errors;
+ int avg_svc_time;
+ int ghbn_calls; /* # calls to blocking gethostbyname() */
+ int dnsserver_hist[DefaultDnsChildrenMax];
+} IpcacheStats;
typedef struct _line_entry {
char *line;
struct _line_entry *next;
} line_entry;
-static dnsserver_entry **dns_child_table = NULL;
-static int last_dns_dispatched = 2;
+struct dnsQueueData {
+ struct dnsQueueData *next;
+ ipcache_entry *ip_entry;
+};
+
+static int ipcache_testname _PARAMS((void));
+static dnsserver_t *dnsGetFirstAvailable _PARAMS((void));
+static int ipcache_compareLastRef _PARAMS((ipcache_entry **, ipcache_entry **));
+static int ipcache_create_dnsserver _PARAMS((char *command));
+static int ipcache_dnsHandleRead _PARAMS((int, dnsserver_t *));
+static int ipcache_parsebuffer _PARAMS((char *buf, unsigned int offset, dnsserver_t *));
+static int ipcache_purgelru _PARAMS((void));
+static void ipcache_release _PARAMS((ipcache_entry *));
+static ipcache_entry *ipcache_GetFirst _PARAMS((void));
+static ipcache_entry *ipcache_GetNext _PARAMS((void));
+static ipcache_entry *ipcache_create _PARAMS((void));
+static void free_lines _PARAMS((line_entry *));
+static void ipcache_add_to_hash _PARAMS((ipcache_entry *));
+static void ipcache_call_pending _PARAMS((ipcache_entry *));
+static void ipcache_call_pending_badname _PARAMS((int fd, IPH handler, void *));
+static void ipcache_add _PARAMS((char *, ipcache_entry *, struct hostent *, int));
+static ipcache_entry *dnsDequeue _PARAMS(());
+static void dnsEnqueue _PARAMS((ipcache_entry *));
+static void dnsDispatch _PARAMS((dnsserver_t *, ipcache_entry *));
+static int ipcacheHasPending _PARAMS((ipcache_entry *));
+static ipcache_entry *ipcache_get _PARAMS((char *));
+static int dummy_handler _PARAMS((int, struct hostent * hp, void *));
+static int ipcacheExpiredEntry _PARAMS((ipcache_entry *));
+static void ipcacheAddPending _PARAMS((ipcache_entry *, int fd, IPH, void *));
+
+static dnsserver_t **dns_child_table = NULL;
static struct hostent *static_result = NULL;
-static int dns_child_alive = 0;
-
+static int NDnsServersAlloc = 0;
+static struct dnsQueueData *dnsQueueHead = NULL;
+static struct dnsQueueData **dnsQueueTailP = &dnsQueueHead;
+static HashID ip_table = 0;
char *dns_error_message = NULL; /* possible error message */
-HashID ip_table = 0;
-
-extern int do_dns_test;
-extern int getMaxFD();
-extern int getDnsChildren();
-extern void fatal_dump _PARAMS((char *));
-extern int file_update_open _PARAMS((int, char *));
+long ipcache_low = 180;
+long ipcache_high = 200;
-void update_dns_child_alive()
+static char ipcache_status_char[] =
{
- int i;
- int N = getDnsChildren();
-
- dns_child_alive = 0;
- for (i = 0; i < N; ++i) {
- if (dns_child_table[i]->alive) {
- dns_child_alive = 1;
- break;
- }
- }
-}
+ 'C',
+ 'N',
+ 'P',
+ 'D'
+};
-int ipcache_testname()
+static int ipcache_testname()
{
wordlist *w = NULL;
debug(14, 1, "Performing DNS Tests...\n");
if ((w = getDnsTestnameList()) == NULL)
return 1;
for (; w; w = w->next) {
+ IpcacheStats.ghbn_calls++;
if (gethostbyname(w->key) != NULL)
return 1;
}
return 0;
}
-
-/*
- * open a UNIX domain socket for rendevouing with dnsservers
- */
-int ipcache_create_dnsserver(command)
+/* TCP SOCKET VERSION */
+static int ipcache_create_dnsserver(command)
char *command;
{
int pid;
- struct sockaddr_un addr;
- static int n_dnsserver = 0;
- char *socketname = NULL;
- int cfd; /* socket for child (dnsserver) */
- int sfd; /* socket for server (squid) */
+ u_short port;
+ struct sockaddr_in S;
+ int cfd;
+ int sfd;
+ int len;
int fd;
- if ((cfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- debug(14, 0, "ipcache_create_dnsserver: socket: %s\n", xstrerror());
+ cfd = comm_open(COMM_NOCLOEXEC,
+ local_addr,
+ 0,
+ "socket to dnsserver");
+ if (cfd == COMM_ERROR) {
+ debug(14, 0, "ipcache_create_dnsserver: Failed to create dnsserver\n");
return -1;
}
- fdstat_open(cfd, Socket);
- fd_note(cfd, "socket to dnsserver");
- memset(&addr, '\0', sizeof(addr));
- addr.sun_family = AF_UNIX;
- socketname = tempnam(NULL, "dns");
- /* sprintf(socketname, "dns/dns%d.%d", (int) getpid(), n_dnsserver++); */
- strcpy(addr.sun_path, socketname);
- debug(14, 4, "ipcache_create_dnsserver: path is %s\n", addr.sun_path);
-
- if (bind(cfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(cfd);
- debug(14, 0, "ipcache_create_dnsserver: bind: %s\n", xstrerror());
- xfree(socketname);
+ len = sizeof(S);
+ memset(&S, '\0', len);
+ if (getsockname(cfd, (struct sockaddr *) &S, &len) < 0) {
+ debug(14, 0, "ipcache_create_dnsserver: getsockname: %s\n", xstrerror());
+ comm_close(cfd);
return -1;
}
+ port = ntohs(S.sin_port);
debug(14, 4, "ipcache_create_dnsserver: bind to local host.\n");
listen(cfd, 1);
-
if ((pid = fork()) < 0) {
debug(14, 0, "ipcache_create_dnsserver: fork: %s\n", xstrerror());
- close(cfd);
- xfree(socketname);
+ comm_close(cfd);
return -1;
}
if (pid > 0) { /* parent */
- close(cfd); /* close shared socket with child */
-
+ comm_close(cfd); /* close shared socket with child */
/* open new socket for parent process */
- if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- debug(14, 0, "ipcache_create_dnsserver: socket: %s\n", xstrerror());
- xfree(socketname);
+ sfd = comm_open(0, local_addr, 0, NULL); /* blocking! */
+ if (sfd == COMM_ERROR)
return -1;
- }
- fcntl(sfd, F_SETFD, 1); /* set close-on-exec */
- memset(&addr, '\0', sizeof(addr));
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, socketname);
- xfree(socketname);
- if (connect(sfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(sfd);
- debug(14, 0, "ipcache_create_dnsserver: connect: %s\n", xstrerror());
+ if (comm_connect(sfd, localhost, port) == COMM_ERROR) {
+ comm_close(sfd);
return -1;
}
- debug(14, 4, "ipcache_create_dnsserver: FD %d connected to %s #%d.\n",
- sfd, command, n_dnsserver);
+ comm_set_fd_lifetime(sfd, -1);
return sfd;
}
/* child */
- /* give up extra priviliges */
- no_suid();
-
- /* setup filedescriptors */
+ no_suid(); /* give up extra priviliges */
dup2(cfd, 3);
- for (fd = getMaxFD(); fd > 3; fd--) {
- (void) close(fd);
- }
-
- execlp(command, "(dnsserver)", "-p", socketname, NULL);
+ for (fd = FD_SETSIZE; fd > 3; fd--)
+ close(fd);
+ execlp(command, "(dnsserver)", "-t", NULL);
debug(14, 0, "ipcache_create_dnsserver: %s: %s\n", command, xstrerror());
_exit(1);
- return (0); /* NOTREACHED */
+ return 0;
}
-
/* removes the given ipcache entry */
-int ipcache_release(e)
- ipcache_entry *e;
+static void ipcache_release(i)
+ ipcache_entry *i;
{
ipcache_entry *result = 0;
- int i;
+ hash_link *table_entry = NULL;
+ int k;
- debug(14, 5, "ipcache_release: ipcache_count before: %d \n", meta_data.ipcache_count);
-
- if (e != NULL && ip_table) { /* sometimes called with NULL e */
- hash_link *table_entry = hash_lookup(ip_table, e->name);
- if (table_entry) {
- result = (ipcache_entry *) table_entry;
- debug(14, 5, "HASH table count before delete: %d\n", ipcache_hash_entry_count());
- if (hash_remove_link(ip_table, table_entry)) {
- debug(14, 3, "ipcache_release: Cannot delete '%s' from hash table %d\n", e->name, ip_table);
- }
- debug(14, 5, "HASH table count after delete: %d\n", ipcache_hash_entry_count());
- if (result) {
- if (result->status == PENDING) {
- debug(14, 1, "ipcache_release: Try to release entry with PENDING status. ignored.\n");
- debug(14, 5, "ipcache_release: ipcache_count: %d \n", meta_data.ipcache_count);
- return -1;
- }
- if (result->status == CACHED) {
- if (result->addr_count)
- for (i = 0; i < (int) result->addr_count; i++)
- safe_free(result->entry.h_addr_list[i]);
- if (result->entry.h_addr_list)
- safe_free(result->entry.h_addr_list);
- if (result->alias_count)
- for (i = 0; i < (int) result->alias_count; i++)
- safe_free(result->entry.h_aliases[i]);
- if (result->entry.h_aliases)
- safe_free(result->entry.h_aliases);
- safe_free(result->entry.h_name);
- debug(14, 5, "ipcache_release: Released IP cached record for '%s'.\n", e->name);
- }
- /* XXX: we're having mem mgmt problems; zero, then free */
- safe_free(result->name);
- memset(result, '\0', sizeof(ipcache_entry));
- safe_free(result);
- }
- --meta_data.ipcache_count;
- debug(14, 5, "ipcache_release: ipcache_count when return: %d \n", meta_data.ipcache_count);
- return meta_data.ipcache_count;
- }
+ if ((table_entry = hash_lookup(ip_table, i->name)) == NULL) {
+ debug(14, 0, "ipcache_release: Could not find key '%s'\n", i->name);
+ return;
+ }
+ result = (ipcache_entry *) table_entry;
+ if (i != result)
+ fatal_dump("ipcache_release: expected i == result!");
+ if (i->status == IP_PENDING) {
+ debug(14, 1, "ipcache_release: Someone called on a PENDING entry\n");
+ return;
+ }
+ if (i->status == IP_DISPATCHED) {
+ debug(14, 1, "ipcache_release: Someone called on a DISPATCHED entry\n");
+ return;
}
- debug(14, 3, "ipcache_release: can't delete entry\n");
- return -1; /* can't delete entry */
+ if (hash_remove_link(ip_table, table_entry)) {
+ debug(14, 0, "ipcache_release: hash_remove_link() failed for '%s'\n",
+ result->name);
+ return;
+ }
+ if (result->status == IP_CACHED) {
+ for (k = 0; k < (int) result->addr_count; k++)
+ safe_free(result->entry.h_addr_list[k]);
+ safe_free(result->entry.h_addr_list);
+ for (k = 0; k < (int) result->alias_count; k++)
+ safe_free(result->entry.h_aliases[k]);
+ if (result->entry.h_aliases)
+ safe_free(result->entry.h_aliases);
+ safe_free(result->entry.h_name);
+ debug(14, 5, "ipcache_release: Released IP cached record for '%s'.\n",
+ result->name);
+ }
+ safe_free(result->name);
+ safe_free(result->error_message);
+ memset(result, '\0', sizeof(ipcache_entry));
+ safe_free(result);
+ --meta_data.ipcache_count;
+ return;
}
/* return match for given name */
-ipcache_entry *ipcache_get(name)
+static ipcache_entry *ipcache_get(name)
char *name;
{
hash_link *e;
- static ipcache_entry *result;
+ static ipcache_entry *i;
- result = NULL;
+ i = NULL;
if (ip_table) {
if ((e = hash_lookup(ip_table, name)) != NULL)
- result = (ipcache_entry *) e;
- }
- if (result == NULL)
- return NULL;
-
- if (((result->timestamp + result->ttl) < squid_curtime) &&
- (result->status != PENDING)) { /* expired? */
- ipcache_release(result);
- return NULL;
+ i = (ipcache_entry *) e;
}
- return result;
+ return i;
}
-
/* get the first ip entry in the storage */
-ipcache_entry *ipcache_GetFirst()
+static ipcache_entry *ipcache_GetFirst()
{
- static hash_link *entryPtr;
-
- if ((!ip_table) || ((entryPtr = hash_first(ip_table)) == NULL))
- return NULL;
- return ((ipcache_entry *) entryPtr);
+ return (ipcache_entry *) hash_first(ip_table);
}
-
/* get the next ip entry in the storage for a given search pointer */
-ipcache_entry *ipcache_GetNext()
+static ipcache_entry *ipcache_GetNext()
{
- static hash_link *entryPtr;
-
- if ((!ip_table) || ((entryPtr = hash_next(ip_table)) == NULL))
- return NULL;
- return ((ipcache_entry *) entryPtr);
+ return (ipcache_entry *) hash_next(ip_table);
}
-int ipcache_compareLastRef(e1, e2)
+static int ipcache_compareLastRef(e1, e2)
ipcache_entry **e1, **e2;
{
if (!e1 || !e2)
fatal_dump(NULL);
-
if ((*e1)->lastref > (*e2)->lastref)
return (1);
-
if ((*e1)->lastref < (*e2)->lastref)
return (-1);
-
return (0);
}
-
+static int ipcacheExpiredEntry(i)
+ ipcache_entry *i;
+{
+ if (i->lock)
+ return 0;
+ if (i->status == IP_PENDING)
+ return 0;
+ if (i->status == IP_DISPATCHED)
+ return 0;
+ if (i->ttl + i->lastref > squid_curtime)
+ return 0;
+ return 1;
+}
/* finds the LRU and deletes */
-int ipcache_purgelru()
+static int ipcache_purgelru()
{
- ipcache_entry *e;
+ ipcache_entry *i = NULL;
int local_ip_count = 0;
int local_ip_notpending_count = 0;
int removed = 0;
- int i;
- ipcache_entry **LRU_list;
+ int k;
+ ipcache_entry **LRU_list = NULL;
int LRU_list_count = 0;
int LRU_cur_size = meta_data.ipcache_count;
- LRU_list = (ipcache_entry **) xcalloc(LRU_cur_size, sizeof(ipcache_entry *));
+ LRU_list = xcalloc(LRU_cur_size, sizeof(ipcache_entry *));
- e = NULL;
-
- for (e = ipcache_GetFirst(); e; e = ipcache_GetNext()) {
+ for (i = ipcache_GetFirst(); i; i = ipcache_GetNext()) {
+ if (ipcacheExpiredEntry(i)) {
+ ipcache_release(i);
+ removed++;
+ continue;
+ }
local_ip_count++;
if (LRU_list_count >= LRU_cur_size) {
LRU_cur_size += 16;
debug(14, 3, "ipcache_purgelru: Have to grow LRU_list to %d. This shouldn't happen.\n",
LRU_cur_size);
- LRU_list = (ipcache_entry **) xrealloc((char *) LRU_list,
+ LRU_list = xrealloc((char *) LRU_list,
LRU_cur_size * sizeof(ipcache_entry *));
}
- if ((e->status != PENDING) && (e->pending_head == NULL)) {
- local_ip_notpending_count++;
- LRU_list[LRU_list_count++] = e;
- }
+ if (i->status == IP_PENDING)
+ continue;
+ if (i->status == IP_DISPATCHED)
+ continue;
+ if (i->lock)
+ continue;
+ local_ip_notpending_count++;
+ LRU_list[LRU_list_count++] = i;
}
debug(14, 3, "ipcache_purgelru: ipcache_count: %5d\n", meta_data.ipcache_count);
debug(14, 3, " actual count : %5d\n", local_ip_count);
- debug(14, 3, " high W mark : %5d\n", ipcache_high);
- debug(14, 3, " low W mark : %5d\n", ipcache_low);
- debug(14, 3, " not pending : %5d\n", local_ip_notpending_count);
- debug(14, 3, " LRU candidated : %5d\n", LRU_list_count);
+ debug(14, 3, " high W mark : %5d\n", ipcache_high);
+ debug(14, 3, " low W mark : %5d\n", ipcache_low);
+ debug(14, 3, " not pending : %5d\n", local_ip_notpending_count);
+ debug(14, 3, " LRU candidates : %5d\n", LRU_list_count);
/* sort LRU candidate list */
- qsort((char *) LRU_list, LRU_list_count, sizeof(e), (int (*)(const void *, const void *)) ipcache_compareLastRef);
-
- for (i = 0; LRU_list[i] && (meta_data.ipcache_count > ipcache_low)
- && i < LRU_list_count;
- ++i) {
- ipcache_release(LRU_list[i]);
+ qsort((char *) LRU_list,
+ LRU_list_count,
+ sizeof(i),
+ (int (*)(const void *, const void *)) ipcache_compareLastRef);
+ for (k = 0; LRU_list[k] && (meta_data.ipcache_count > ipcache_low)
+ && k < LRU_list_count;
+ ++k) {
+ ipcache_release(LRU_list[k]);
removed++;
}
- debug(14, 3, " removed : %5d\n", removed);
+ debug(14, 3, " removed : %5d\n", removed);
safe_free(LRU_list);
return (removed > 0) ? 0 : -1;
}
/* create blank ipcache_entry */
-ipcache_entry *ipcache_create()
+static ipcache_entry *ipcache_create()
{
- static ipcache_entry *ipe;
static ipcache_entry *new;
- debug(14, 5, "ipcache_create: when enter. ipcache_count == %d\n", meta_data.ipcache_count);
if (meta_data.ipcache_count > ipcache_high) {
- if (ipcache_purgelru() < 0) {
- debug(14, 1, "ipcache_create: Cannot release needed IP entry via LRU: %d > %d, removing first entry...\n", meta_data.ipcache_count, MAX_IP);
- ipe = ipcache_GetFirst();
- if (!ipe) {
- debug(14, 1, "ipcache_create: First entry is a null pointer ???\n");
- /* have to let it grow beyond limit here */
- } else if (ipe && ipe->status != PENDING) {
- ipcache_release(ipe);
- } else {
- debug(14, 1, "ipcache_create: First entry is also PENDING entry.\n");
- /* have to let it grow beyond limit here */
- }
- }
+ if (ipcache_purgelru() < 0)
+ debug(14, 0, "HELP!! IP Cache is overflowing!\n");
}
meta_data.ipcache_count++;
- debug(14, 5, "ipcache_create: before return. ipcache_count == %d\n", meta_data.ipcache_count);
- new = (ipcache_entry *) xcalloc(1, sizeof(ipcache_entry));
+ new = xcalloc(1, sizeof(ipcache_entry));
/* set default to 4, in case parser fail to get token $h_length from
* dnsserver. */
new->entry.h_length = 4;
}
-void ipcache_add_to_hash(e)
- ipcache_entry *e;
+static void ipcache_add_to_hash(i)
+ ipcache_entry *i;
{
- if (hash_join(ip_table, (hash_link *) e)) {
+ if (hash_join(ip_table, (hash_link *) i)) {
debug(14, 1, "ipcache_add_to_hash: Cannot add %s (%p) to hash table %d.\n",
- e->name, e, ip_table);
+ i->name, i, ip_table);
}
- debug(14, 5, "ipcache_add_to_hash: name <%s>\n", e->name);
- debug(14, 5, " ipcache_count: %d\n", meta_data.ipcache_count);
+ debug(14, 5, "ipcache_add_to_hash: name <%s>\n", i->name);
}
-void ipcache_add(name, e, data, cached)
+static void ipcache_add(name, i, hp, cached)
char *name;
- ipcache_entry *e;
- struct hostent *data;
+ ipcache_entry *i;
+ struct hostent *hp;
int cached;
{
- int addr_count, alias_count, i;
+ int addr_count;
+ int alias_count;
+ int k;
+ if (ipcache_get(name))
+ fatal_dump("ipcache_add: somebody adding a duplicate!");
debug(14, 10, "ipcache_add: Adding name '%s' (%s).\n", name,
cached ? "cached" : "not cached");
-
- e->name = xstrdup(name);
+ i->name = xstrdup(name);
if (cached) {
-
/* count for IPs */
addr_count = 0;
- while ((addr_count < 255) && data->h_addr_list[addr_count])
+ while ((addr_count < 255) && hp->h_addr_list[addr_count])
++addr_count;
- e->addr_count = addr_count;
+ i->addr_count = addr_count;
/* count for Alias */
alias_count = 0;
- if (data->h_aliases)
- while ((alias_count < 255) && data->h_aliases[alias_count])
+ if (hp->h_aliases)
+ while ((alias_count < 255) && hp->h_aliases[alias_count])
++alias_count;
- e->alias_count = alias_count;
+ i->alias_count = alias_count;
/* copy ip addresses information */
- e->entry.h_addr_list = (char **) xcalloc(addr_count + 1, sizeof(char *));
- for (i = 0; i < addr_count; i++) {
- e->entry.h_addr_list[i] = (char *) xcalloc(1, data->h_length);
- memcpy(e->entry.h_addr_list[i], data->h_addr_list[i], data->h_length);
+ i->entry.h_addr_list = xcalloc(addr_count + 1, sizeof(char *));
+ for (k = 0; k < addr_count; k++) {
+ i->entry.h_addr_list[k] = xcalloc(1, hp->h_length);
+ xmemcpy(i->entry.h_addr_list[k], hp->h_addr_list[k], hp->h_length);
}
if (alias_count) {
/* copy aliases information */
- e->entry.h_aliases = (char **) xcalloc(alias_count + 1, sizeof(char *));
- for (i = 0; i < alias_count; i++) {
- e->entry.h_aliases[i] = (char *) xcalloc(1, strlen(data->h_aliases[i]) + 1);
- strcpy(e->entry.h_aliases[i], data->h_aliases[i]);
+ i->entry.h_aliases = xcalloc(alias_count + 1, sizeof(char *));
+ for (k = 0; k < alias_count; k++) {
+ i->entry.h_aliases[k] = xcalloc(1, strlen(hp->h_aliases[k]) + 1);
+ strcpy(i->entry.h_aliases[k], hp->h_aliases[k]);
}
}
- e->entry.h_length = data->h_length;
- e->entry.h_name = xstrdup(data->h_name);
- e->lastref = e->timestamp = squid_curtime;
- e->status = CACHED;
- e->ttl = DnsPositiveTtl;
+ i->entry.h_length = hp->h_length;
+ i->entry.h_name = xstrdup(hp->h_name);
+ i->lastref = i->timestamp = squid_curtime;
+ i->status = IP_CACHED;
+ i->ttl = DnsPositiveTtl;
} else {
- e->lastref = e->timestamp = squid_curtime;
- e->status = NEGATIVE_CACHED;
- e->ttl = getNegativeDNSTTL();
+ i->lastref = i->timestamp = squid_curtime;
+ i->status = IP_NEGATIVE_CACHED;
+ i->ttl = getNegativeDNSTTL();
}
-
- ipcache_add_to_hash(e);
+ ipcache_add_to_hash(i);
}
-/* exactly the same to ipcache_add,
- * except it does NOT
- * - create entry->name (assume it's there already.)
- * - add the entry to the hash (it's should be in hash table already.).
- *
- * Intend to be used by ipcache_cleanup_pendinglist.
- */
-void ipcache_update_content(name, e, data, cached)
- char *name;
- ipcache_entry *e;
- struct hostent *data;
- int cached;
-{
- int addr_count, alias_count, i;
-
- debug(14, 10, "ipcache_update: Updating name '%s' (%s).\n", name,
- cached ? "cached" : "not cached");
-
- if (cached) {
-
- /* count for IPs */
- addr_count = 0;
- while ((addr_count < 255) && data->h_addr_list[addr_count])
- ++addr_count;
-
- e->addr_count = addr_count;
-
- /* count for Alias */
- alias_count = 0;
- while ((alias_count < 255) && data->h_aliases[alias_count])
- ++alias_count;
-
- e->alias_count = alias_count;
-
- /* copy ip addresses information */
- e->entry.h_addr_list = (char **) xcalloc(addr_count + 1, sizeof(char *));
- for (i = 0; i < addr_count; i++) {
- e->entry.h_addr_list[i] = (char *) xcalloc(1, data->h_length);
- memcpy(e->entry.h_addr_list[i], data->h_addr_list[i], data->h_length);
- }
-
- /* copy aliases information */
- e->entry.h_aliases = (char **) xcalloc(alias_count + 1, sizeof(char *));
- for (i = 0; i < alias_count; i++) {
- e->entry.h_aliases[i] = (char *) xcalloc(1, strlen(data->h_aliases[i]) + 1);
- strcpy(e->entry.h_aliases[i], data->h_aliases[i]);
- }
-
- e->entry.h_length = data->h_length;
- e->entry.h_name = xstrdup(data->h_name);
- e->lastref = e->timestamp = squid_curtime;
- e->status = CACHED;
- e->ttl = DnsPositiveTtl;
- } else {
- e->lastref = e->timestamp = squid_curtime;
- e->status = NEGATIVE_CACHED;
- e->ttl = getNegativeDNSTTL();
- }
-
-}
-
/* walks down the pending list, calling handlers */
-void ipcache_call_pending(entry)
- ipcache_entry *entry;
+static void ipcache_call_pending(i)
+ ipcache_entry *i;
{
- IpPending *p;
+ struct _ip_pending *p = NULL;
int nhandler = 0;
- entry->lastref = squid_curtime;
+ i->lastref = squid_curtime;
- while (entry->pending_head != NULL) {
- p = entry->pending_head;
- entry->pending_head = entry->pending_head->next;
- if (entry->pending_head == NULL)
- entry->pending_tail = NULL;
- if (p->handler != NULL) {
+ while (i->pending_head != NULL) {
+ p = i->pending_head;
+ i->pending_head = p->next;
+ if (p->handler) {
nhandler++;
- p->handler(p->fd, (entry->status == CACHED) ?
- &(entry->entry) : NULL, p->data);
+ dns_error_message = i->error_message;
+ p->handler(p->fd,
+ (i->status == IP_CACHED) ? &(i->entry) : NULL,
+ p->handlerData);
}
- memset(p, '\0', sizeof(IpPending));
+ memset(p, '\0', sizeof(struct _ip_pending));
safe_free(p);
}
- entry->pending_head = entry->pending_tail = NULL; /* nuke list */
+ i->pending_head = NULL; /* nuke list */
debug(14, 10, "ipcache_call_pending: Called %d handlers.\n", nhandler);
}
-void ipcache_call_pending_badname(fd, handler, data)
+static void ipcache_call_pending_badname(fd, handler, data)
int fd;
IPH handler;
void *data;
{
- debug(14, 4, "ipcache_call_pending_badname: Bad Name: Calling handler with NULL result.\n");
+ debug(14, 0, "ipcache_call_pending_badname: Bad Name: Calling handler with NULL result.\n");
handler(fd, NULL, data);
}
-
-/* call when dnsserver is broken, have to switch to blocking mode.
- * All pending lookup will be looked up by blocking call.
- */
-int ipcache_cleanup_pendinglist(data)
- dnsserver_entry *data;
-{
- ipcache_list *p;
- struct hostent *s_result = NULL;
-
- while (data->global_pending != NULL) {
- s_result = gethostbyname(data->global_pending->entry->name);
- ipcache_update_content(data->global_pending->entry->name,
- data->global_pending->entry, s_result, s_result ? 1 : 0);
- ipcache_call_pending(data->global_pending->entry);
- p = data->global_pending;
- data->global_pending = data->global_pending->next;
- /* XXX: we're having mem mgmt problems; zero, then free */
- memset(p, '\0', sizeof(ipcache_list));
- safe_free(p);
- }
- data->global_pending = data->global_pending_tail = NULL; /* nuke */
- return 0;
-}
-
/* free all lines in the list */
-void free_lines(line)
+static void free_lines(line)
line_entry *line;
{
line_entry *tmp;
}
}
-/* return entry in global pending list that has entry which key match to name */
-ipcache_list *globalpending_search(name, global_pending)
- char *name;
- ipcache_list *global_pending;
-{
- static ipcache_list *p;
-
- if (name == NULL)
- return NULL;
-
- for (p = global_pending; p != NULL; p = p->next) {
- /* XXX: this is causing core dumps! p->entry is corrupt */
- if (p->entry && p->entry->name &&
- strcmp(p->entry->name, name) == 0) {
- return p;
- }
- }
- return NULL;
-
-}
-
-/* remove entry from global pending list */
-void globalpending_remove(p, data)
- ipcache_list *p;
- dnsserver_entry *data;
-{
- ipcache_list *q, *r;
-
- r = q = data->global_pending;
- while (q && (p != q)) {
- r = q; /* r is the node before the one to kill */
- q = q->next; /* q (and 'p') is the node to kill */
- }
-
- if (q == NULL) { /* 'p' is not in the list? */
- debug(14, 1, "globalpending_remove: Failure while deleting entry from global pending list.\n");
- return;
- }
- /* nuke p from the list; do this carefully... */
- if (p == data->global_pending) { /* p is head */
- if (p->next != NULL) { /* nuke head */
- data->global_pending = p->next;
- } else { /* nuke whole list */
- data->global_pending = NULL;
- data->global_pending_tail = NULL;
- }
- } else if (p == data->global_pending_tail) { /* p is tail */
- data->global_pending_tail = r; /* tail is prev */
- data->global_pending_tail->next = NULL; /* last node */
- } else { /* p in middle */
- r->next = p->next;
- }
-
- /* we need to delete all references to p */
- /* XXX: we're having mem mgmt probs; zero then free DRH */
- memset(p, '\0', sizeof(ipcache_list));
- /* XXX: what about freeing p->entry? DRH */
- safe_free(p);
-
- if (data->pending_count > 0)
- data->pending_count--;
-
-}
-
/* scan through buffer and do a conversion if possible
* return number of char used */
-int ipcache_parsebuffer(buf, offset, data)
+static int ipcache_parsebuffer(buf, offset, dnsData)
char *buf;
unsigned int offset;
- dnsserver_entry *data;
+ dnsserver_t *dnsData;
{
char *pos = NULL;
char *tpos = NULL;
line_entry *line_head = NULL;
line_entry *line_tail = NULL;
line_entry *line_cur = NULL;
- ipcache_list *plist = NULL;
+ int ipcount;
+ int aliascount;
+ ipcache_entry *i = NULL;
- *dns_error_message = '\0';
pos = buf;
while (pos < (buf + offset)) {
while (pos < endpos) {
/* add the next line to the end of the list */
- line_cur = (line_entry *) xcalloc(1, sizeof(line_entry));
+ line_cur = xcalloc(1, sizeof(line_entry));
if ((tpos = memchr(pos, '\n', 4096)) == NULL) {
debug(14, 2, "ipcache_parsebuffer: DNS response incomplete.\n");
* Start parsing...
*/
if (strstr(line_head->line, "$alive")) {
- data->answer = squid_curtime;
+ dnsData->answer = squid_curtime;
free_lines(line_head);
debug(14, 10, "ipcache_parsebuffer: $alive succeeded.\n");
} else if (strstr(line_head->line, "$fail")) {
* $fail host\n$message msg\n$end\n
*/
token = strtok(line_head->line, w_space); /* skip first token */
- token = strtok(NULL, w_space);
-
- line_cur = line_head->next;
- if (line_cur && !strncmp(line_cur->line, "$message", 8)) {
- strcpy(dns_error_message, line_cur->line + 8);
- }
- if (token == NULL) {
- debug(14, 1, "ipcache_parsebuffer: Invalid $fail for DNS table?\n");
+ if ((token = strtok(NULL, w_space)) == NULL) {
+ debug(14, 1, "ipcache_parsebuffer: Invalid $fail?\n");
} else {
- plist = globalpending_search(token, data->global_pending);
- if (plist) {
- plist->entry->lastref = plist->entry->timestamp = squid_curtime;
- plist->entry->ttl = getNegativeDNSTTL();
- plist->entry->status = NEGATIVE_CACHED;
- ipcache_call_pending(plist->entry);
- globalpending_remove(plist, data);
- debug(14, 10, "ipcache_parsebuffer: $fail succeeded: %s.\n",
- dns_error_message[0] ? dns_error_message : "why?");
- } else {
- debug(14, 1, "ipcache_parsebuffer: No entry in DNS table?\n");
- }
+ line_cur = line_head->next;
+ i = dnsData->ip_entry;
+ i->lastref = i->timestamp = squid_curtime;
+ i->ttl = getNegativeDNSTTL();
+ i->status = IP_NEGATIVE_CACHED;
+ if (line_cur && !strncmp(line_cur->line, "$message", 8))
+ i->error_message = xstrdup(line_cur->line + 8);
+ dns_error_message = i->error_message;
+ ipcache_call_pending(i);
}
free_lines(line_head);
} else if (strstr(line_head->line, "$name")) {
tmp_ptr = line_head->line;
/* skip the first token */
token = strtok(tmp_ptr, w_space);
- tmp_ptr = NULL;
- token = strtok(tmp_ptr, w_space);
- if (!token) {
- debug(14, 1, "ipcache_parsebuffer: Invalid OPCODE for DNS table?\n");
+ if ((token = strtok(NULL, w_space)) == NULL) {
+ debug(14, 0, "ipcache_parsebuffer: Invalid OPCODE?\n");
} else {
- plist = globalpending_search(token, data->global_pending);
- if (plist) {
- int ipcount, aliascount;
- ipcache_entry *e = plist->entry;
-
- if (e->status != PENDING) {
- debug(14, 4, "ipcache_parsebuffer: DNS record already resolved.\n");
+ i = dnsData->ip_entry;
+ if (i->status != IP_DISPATCHED) {
+ debug(14, 0, "ipcache_parsebuffer: DNS record already resolved.\n");
+ } else {
+ i->lastref = i->timestamp = squid_curtime;
+ i->ttl = DnsPositiveTtl;
+ i->status = IP_CACHED;
+
+ line_cur = line_head->next;
+
+ /* get $h_name */
+ if (line_cur == NULL ||
+ !strstr(line_cur->line, "$h_name")) {
+ debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $h_name.\n");
+ /* abandon this record */
+ break;
+ }
+ tmp_ptr = line_cur->line;
+ /* skip the first token */
+ token = strtok(tmp_ptr, w_space);
+ tmp_ptr = NULL;
+ token = strtok(tmp_ptr, w_space);
+ i->entry.h_name = xstrdup(token);
+
+ line_cur = line_cur->next;
+
+ /* get $h_length */
+ if (line_cur == NULL ||
+ !strstr(line_cur->line, "$h_len")) {
+ debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $h_len.\n");
+ /* abandon this record */
+ break;
+ }
+ tmp_ptr = line_cur->line;
+ /* skip the first token */
+ token = strtok(tmp_ptr, w_space);
+ tmp_ptr = NULL;
+ token = strtok(tmp_ptr, w_space);
+ i->entry.h_length = atoi(token);
+
+ line_cur = line_cur->next;
+
+ /* get $ipcount */
+ if (line_cur == NULL ||
+ !strstr(line_cur->line, "$ipcount")) {
+ debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $ipcount.\n");
+ /* abandon this record */
+ break;
+ }
+ tmp_ptr = line_cur->line;
+ /* skip the first token */
+ token = strtok(tmp_ptr, w_space);
+ tmp_ptr = NULL;
+ token = strtok(tmp_ptr, w_space);
+ i->addr_count = ipcount = atoi(token);
+
+ if (ipcount == 0) {
+ i->entry.h_addr_list = NULL;
} else {
- e->lastref = e->timestamp = squid_curtime;
- e->ttl = DnsPositiveTtl;
- e->status = CACHED;
-
- line_cur = line_head->next;
-
- /* get $h_name */
- if (line_cur == NULL ||
- !strstr(line_cur->line, "$h_name")) {
- debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $h_name.\n");
- /* abandon this record */
- break;
- }
- tmp_ptr = line_cur->line;
- /* skip the first token */
- token = strtok(tmp_ptr, w_space);
- tmp_ptr = NULL;
- token = strtok(tmp_ptr, w_space);
- e->entry.h_name = xstrdup(token);
-
- line_cur = line_cur->next;
-
- /* get $h_length */
- if (line_cur == NULL ||
- !strstr(line_cur->line, "$h_len")) {
- debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $h_len.\n");
- /* abandon this record */
- break;
- }
- tmp_ptr = line_cur->line;
- /* skip the first token */
- token = strtok(tmp_ptr, w_space);
- tmp_ptr = NULL;
- token = strtok(tmp_ptr, w_space);
- e->entry.h_length = atoi(token);
+ i->entry.h_addr_list = xcalloc(ipcount + 1, sizeof(char *));
+ }
+ /* get ip addresses */
+ {
+ int k = 0;
line_cur = line_cur->next;
-
- /* get $ipcount */
- if (line_cur == NULL ||
- !strstr(line_cur->line, "$ipcount")) {
- debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $ipcount.\n");
- /* abandon this record */
- break;
- }
- tmp_ptr = line_cur->line;
- /* skip the first token */
- token = strtok(tmp_ptr, w_space);
- tmp_ptr = NULL;
- token = strtok(tmp_ptr, w_space);
- e->addr_count = ipcount = atoi(token);
-
- if (ipcount == 0) {
- e->entry.h_addr_list = NULL;
- } else {
- e->entry.h_addr_list = (char **) xcalloc(ipcount, sizeof(char *));
- }
-
- /* get ip addresses */
- {
- int i = 0;
- line_cur = line_cur->next;
- while (i < ipcount) {
- if (line_cur == NULL) {
- debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $ipcount data.\n");
- break;
- }
- e->entry.h_addr_list[i] = (char *) xcalloc(1, e->entry.h_length);
- *((unsigned long *) (void *) e->entry.h_addr_list[i]) = inet_addr(line_cur->line);
- line_cur = line_cur->next;
- i++;
+ while (k < ipcount) {
+ if (line_cur == NULL) {
+ debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $ipcount data.\n");
+ break;
}
+ i->entry.h_addr_list[k] = xcalloc(1, i->entry.h_length);
+ *((u_num32 *) (void *) i->entry.h_addr_list[k]) = inet_addr(line_cur->line);
+ line_cur = line_cur->next;
+ k++;
}
+ }
- /* get $aliascount */
- if (line_cur == NULL ||
- !strstr(line_cur->line, "$aliascount")) {
- debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $aliascount.\n");
- /* abandon this record */
- break;
- }
- tmp_ptr = line_cur->line;
- /* skip the first token */
- token = strtok(tmp_ptr, w_space);
- tmp_ptr = NULL;
- token = strtok(tmp_ptr, w_space);
- e->alias_count = aliascount = atoi(token);
-
- if (aliascount == 0) {
- e->entry.h_aliases = NULL;
- } else {
- e->entry.h_aliases = (char **) xcalloc(aliascount, sizeof(char *));
- }
+ /* get $aliascount */
+ if (line_cur == NULL ||
+ !strstr(line_cur->line, "$aliascount")) {
+ debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $aliascount.\n");
+ /* abandon this record */
+ break;
+ }
+ tmp_ptr = line_cur->line;
+ /* skip the first token */
+ token = strtok(tmp_ptr, w_space);
+ tmp_ptr = NULL;
+ token = strtok(tmp_ptr, w_space);
+ i->alias_count = aliascount = atoi(token);
+
+ if (aliascount == 0) {
+ i->entry.h_aliases = NULL;
+ } else {
+ i->entry.h_aliases = xcalloc(aliascount, sizeof(char *));
+ }
- /* get aliases */
- {
- int i = 0;
- line_cur = line_cur->next;
- while (i < aliascount) {
- if (line_cur == NULL) {
- debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $aliascount data.\n");
- break;
- }
- e->entry.h_aliases[i] = xstrdup(line_cur->line);
- line_cur = line_cur->next;
- i++;
+ /* get aliases */
+ {
+ int k = 0;
+ line_cur = line_cur->next;
+ while (k < aliascount) {
+ if (line_cur == NULL) {
+ debug(14, 1, "ipcache_parsebuffer: DNS record in invalid format? No $aliascount data.\n");
+ break;
}
+ i->entry.h_aliases[k] = xstrdup(line_cur->line);
+ line_cur = line_cur->next;
+ k++;
}
-
- ipcache_call_pending(e);
- globalpending_remove(plist, data);
- debug(14, 10, "ipcache_parsebuffer: $name succeeded.\n");
}
- } else {
- debug(14, 1, "ipcache_parsebuffer: No entries in DNS $name record?\n");
+ ipcache_call_pending(i);
+ debug(14, 10, "ipcache_parsebuffer: $name succeeded.\n");
}
}
free_lines(line_head);
}
-int ipcache_dnsHandleRead(fd, data)
+static int ipcache_dnsHandleRead(fd, dnsData)
int fd;
- dnsserver_entry *data;
+ dnsserver_t *dnsData;
{
int char_scanned;
- int len = read(fd, data->ip_inbuf + data->offset, data->size - data->offset);
-
- debug(14, 5, "ipcache_dnsHandleRead: Result from DNS ID %d.\n", data->id);
-
- if (len == 0) {
- debug(14, 1, "ipcache_dnsHandleRead: Connection from DNSSERVER is closed.\n");
- debug(14, 1, " Disabling this server ID %d.\n", data->id);
- data->alive = 0;
- update_dns_child_alive();
- ipcache_cleanup_pendinglist(data);
- close(fd);
- fdstat_close(fd);
+ int len;
+ int svc_time;
+ int n;
+ ipcache_entry *i = NULL;
+
+ len = read(fd,
+ dnsData->ip_inbuf + dnsData->offset,
+ dnsData->size - dnsData->offset);
+ debug(14, 5, "ipcache_dnsHandleRead: Result from DNS ID %d (%d bytes)\n",
+ dnsData->id, len);
+ if (len <= 0) {
+ debug(14, dnsData->flags & DNS_FLAG_CLOSING ? 5 : 1,
+ "FD %d: Connection from DNSSERVER #%d is closed, disabling\n",
+ fd, dnsData->id);
+ dnsData->flags = 0;
+ comm_set_select_handler(fd,
+ COMM_SELECT_WRITE,
+ NULL,
+ NULL);
+ comm_close(fd);
return 0;
}
- data->offset += len;
- data->ip_inbuf[data->offset] = '\0';
+ n = ++IpcacheStats.dnsserver_replies;
+ dnsData->offset += len;
+ dnsData->ip_inbuf[dnsData->offset] = '\0';
- if (strstr(data->ip_inbuf, "$end\n")) {
+ if (strstr(dnsData->ip_inbuf, "$end\n")) {
/* end of record found */
- char_scanned = ipcache_parsebuffer(data->ip_inbuf, data->offset, data);
+ svc_time = tvSubMsec(dnsData->dispatch_time, current_time);
+ if (n > IPCACHE_AV_FACTOR)
+ n = IPCACHE_AV_FACTOR;
+ IpcacheStats.avg_svc_time
+ = (IpcacheStats.avg_svc_time * (n - 1) + svc_time) / n;
+ char_scanned = ipcache_parsebuffer(dnsData->ip_inbuf,
+ dnsData->offset,
+ dnsData);
if (char_scanned > 0) {
/* update buffer */
- memcpy(data->ip_inbuf, data->ip_inbuf + char_scanned, data->offset - char_scanned);
- data->offset -= char_scanned;
- data->ip_inbuf[data->offset] = '\0';
+ xmemcpy(dnsData->ip_inbuf,
+ dnsData->ip_inbuf + char_scanned,
+ dnsData->offset - char_scanned);
+ dnsData->offset -= char_scanned;
+ dnsData->ip_inbuf[dnsData->offset] = '\0';
}
}
+ if (dnsData->offset == 0) {
+ dnsData->ip_entry = NULL;
+ dnsData->flags &= ~DNS_FLAG_BUSY;
+ }
/* reschedule */
- comm_set_select_handler(data->inpipe, COMM_SELECT_READ,
- (PF) ipcache_dnsHandleRead, (void *) data);
+ comm_set_select_handler(dnsData->inpipe,
+ COMM_SELECT_READ,
+ (PF) ipcache_dnsHandleRead,
+ dnsData);
+ while ((dnsData = dnsGetFirstAvailable()) && (i = dnsDequeue()))
+ dnsDispatch(dnsData, i);
return 0;
}
-int ipcache_nbgethostbyname(name, fd, handler, data)
+static void ipcacheAddPending(i, fd, handler, handlerData)
+ ipcache_entry *i;
+ int fd;
+ IPH handler;
+ void *handlerData;
+{
+ struct _ip_pending *pending = xcalloc(1, sizeof(struct _ip_pending));
+ struct _ip_pending **I = NULL;
+
+ pending->fd = fd;
+ pending->handler = handler;
+ pending->handlerData = handlerData;
+
+ for (I = &(i->pending_head); *I; I = &((*I)->next));
+ *I = pending;
+}
+
+int ipcache_nbgethostbyname(name, fd, handler, handlerData)
char *name;
int fd;
IPH handler;
- void *data;
+ void *handlerData;
{
- ipcache_entry *e;
- IpPending *pending;
- dnsserver_entry *dns;
+ ipcache_entry *i = NULL;
+ dnsserver_t *dnsData = NULL;
+
+ if (!handler)
+ fatal_dump("ipcache_nbgethostbyname: NULL handler");
debug(14, 4, "ipcache_nbgethostbyname: FD %d: Name '%s'.\n", fd, name);
+ IpcacheStats.requests++;
if (name == NULL || name[0] == '\0') {
debug(14, 4, "ipcache_nbgethostbyname: Invalid name!\n");
- ipcache_call_pending_badname(fd, handler, data);
+ ipcache_call_pending_badname(fd, handler, handlerData);
return 0;
}
- if ((e = ipcache_get(name)) != NULL && (e->status != PENDING)) {
- /* hit here */
- debug(14, 4, "ipcache_nbgethostbyname: Hit for name '%s'.\n", name);
- pending = (IpPending *) xcalloc(1, sizeof(IpPending));
- pending->fd = fd;
- pending->handler = handler;
- pending->data = data;
- pending->next = NULL;
- if (e->pending_head == NULL) { /* empty list */
- e->pending_head = e->pending_tail = pending;
- } else { /* add to tail of list */
- e->pending_tail->next = pending;
- e->pending_tail = e->pending_tail->next;
+ if ((i = ipcache_get(name))) {
+ if (ipcacheExpiredEntry(i)) {
+ ipcache_release(i);
+ i = NULL;
}
- ipcache_call_pending(e);
- return 0;
}
- debug(14, 4, "ipcache_nbgethostbyname: Name '%s': MISS or PENDING.\n", name);
-
- pending = (IpPending *) xcalloc(1, sizeof(IpPending));
- pending->fd = fd;
- pending->handler = handler;
- pending->data = data;
- pending->next = NULL;
- if (e == NULL) {
- /* No entry, create the new one */
- debug(14, 5, "ipcache_nbgethostbyname: Creating new entry for '%s'...\n",
- name);
- e = ipcache_create();
- e->name = xstrdup(name);
- e->status = PENDING;
- e->pending_tail = e->pending_head = pending;
- ipcache_add_to_hash(e);
- } else {
- /* There is an entry. Add handler to list */
- debug(14, 5, "ipcache_nbgethostbyname: Adding handler to pending list for '%s'.\n", name);
- if (e->pending_head == NULL) { /* empty list */
- e->pending_head = e->pending_tail = pending;
- } else { /* add to tail of list */
- e->pending_tail->next = pending;
- e->pending_tail = e->pending_tail->next;
- }
+ if (i == NULL) {
+ /* MISS: No entry, create the new one */
+ debug(14, 5, "ipcache_nbgethostbyname: MISS for '%s'\n", name);
+ IpcacheStats.misses++;
+ i = ipcache_create();
+ i->name = xstrdup(name);
+ i->status = IP_PENDING;
+ ipcacheAddPending(i, fd, handler, handlerData);
+ ipcache_add_to_hash(i);
+ } else if (i->status == IP_CACHED || i->status == IP_NEGATIVE_CACHED) {
+ /* HIT */
+ debug(14, 4, "ipcache_nbgethostbyname: HIT for '%s'\n", name);
+ if (i->status == IP_NEGATIVE_CACHED)
+ IpcacheStats.negative_hits++;
+ else
+ IpcacheStats.hits++;
+ ipcacheAddPending(i, fd, handler, handlerData);
+ ipcache_call_pending(i);
return 0;
+ } else if (i->status == IP_PENDING || i->status == IP_DISPATCHED) {
+ debug(14, 4, "ipcache_nbgethostbyname: PENDING for '%s'\n", name);
+ IpcacheStats.pending_hits++;
+ ipcacheAddPending(i, fd, handler, handlerData);
+ return 0;
+ } else {
+ fatal_dump("ipcache_nbgethostbyname: BAD ipcache_entry status");
}
- if (dns_child_alive) {
- int i, j, min_dns = 0, min_count = 255, alive = 0;
-
- j = last_dns_dispatched;
- /* select DNS server with the lowest number of pending */
- for (i = 0; i < getDnsChildren(); ++i) {
- j += 1;
- j %= getDnsChildren();
- if ((dns_child_table[j]->alive) &&
- (dns_child_table[j]->pending_count < min_count)) {
- min_dns = j;
- min_count = dns_child_table[j]->pending_count;
- }
- alive = dns_child_table[j]->alive | alive;
- }
+ /* for HIT, PENDING, DISPATCHED we've returned. For MISS we continue */
- if (alive == 0) {
- dns_child_alive = 0; /* all dead */
- last_dns_dispatched = 0; /* use entry 0 */
- } else {
- last_dns_dispatched = min_dns;
+ if ((dnsData = dnsGetFirstAvailable()))
+ dnsDispatch(dnsData, i);
+ else
+ dnsEnqueue(i);
+ return 0;
+}
+
+static void dnsEnqueue(i)
+ ipcache_entry *i;
+{
+ struct dnsQueueData *new = xcalloc(1, sizeof(struct dnsQueueData));
+ new->ip_entry = i;
+ *dnsQueueTailP = new;
+ dnsQueueTailP = &new->next;
+}
+
+static ipcache_entry *dnsDequeue()
+{
+ struct dnsQueueData *old = NULL;
+ ipcache_entry *i = NULL;
+ if (dnsQueueHead) {
+ i = dnsQueueHead->ip_entry;
+ old = dnsQueueHead;
+ dnsQueueHead = dnsQueueHead->next;
+ if (dnsQueueHead == NULL)
+ dnsQueueTailP = &dnsQueueHead;
+ safe_free(old);
+ }
+#ifdef SANITY_CHECK
+ if (i == NULL) {
+ for (i = ipcache_GetFirst(); i; i = ipcache_GetNext()) {
+ if (i->status == IP_PENDING) { /* This can't happen */
+ debug(14, 0, "IP Cache inconsistency: %s still pending\n",
+ i->name);
+ }
}
- } else {
- last_dns_dispatched = 0;
+ i = NULL;
}
+#endif
+ return i;
+}
- dns = dns_child_table[last_dns_dispatched];
- debug(14, 5, "ipcache_nbgethostbyname: Dispatched DNS %d.\n",
- last_dns_dispatched);
-
- /* add to global pending list */
- if (dns->global_pending == NULL) { /* new list */
- dns->global_pending = (ipcache_list *) xcalloc(1, sizeof(ipcache_list));
- dns->global_pending->entry = e;
- dns->global_pending->next = NULL;
- dns->global_pending_tail = dns->global_pending;
- } else { /* add to end of list */
- ipcache_list *p = (ipcache_list *) xcalloc(1, sizeof(ipcache_list));
- p->entry = e;
- p->next = NULL;
- dns->global_pending_tail->next = p;
- dns->global_pending_tail = dns->global_pending_tail->next;
+static dnsserver_t *dnsGetFirstAvailable()
+{
+ int k;
+ dnsserver_t *dns = NULL;
+ for (k = 0; k < NDnsServersAlloc; k++) {
+ dns = *(dns_child_table + k);
+ if (!(dns->flags & DNS_FLAG_BUSY))
+ return dns;
}
+ return NULL;
+}
- if (dns_child_alive) {
- char *buf = (char *) xcalloc(1, 256);
- strncpy(buf, name, 254);
- strcat(buf, "\n");
- dns->pending_count++;
- file_write(dns->outpipe,
- buf,
- strlen(buf),
- 0, /* Lock */
- 0, /* Handler */
- 0); /* Handler-data */
-
- debug(14, 5, "ipcache_nbgethostbyname: Request sent DNS server ID %d.\n", last_dns_dispatched);
- } else {
- /* do a blocking mode */
- debug(14, 4, "ipcache_nbgethostbyname: Fall back to blocking mode. Server's dead...\n");
- ipcache_cleanup_pendinglist(dns);
+static void dnsDispatch(dns, i)
+ dnsserver_t *dns;
+ ipcache_entry *i;
+{
+ char *buf = NULL;
+ if (!ipcacheHasPending(i)) {
+ debug(14, 0, "dnsDispatch: skipping '%s' because no handler.\n",
+ i->name);
+ i->status = IP_NEGATIVE_CACHED;
+ ipcache_release(i);
+ return;
}
- return 0;
+ i->status = IP_DISPATCHED;
+ buf = xcalloc(1, 256);
+ sprintf(buf, "%1.254s\n", i->name);
+ dns->flags |= DNS_FLAG_BUSY;
+ dns->ip_entry = i;
+ comm_write(dns->outpipe,
+ buf,
+ strlen(buf),
+ 0, /* timeout */
+ NULL, /* Handler */
+ NULL); /* Handler-data */
+ debug(14, 5, "dnsDispatch: Request sent to DNS server #%d.\n",
+ dns->id);
+ dns->dispatch_time = current_time;
+ IpcacheStats.dnsserver_requests++;
+ IpcacheStats.dnsserver_hist[dns->id - 1]++;
}
{
int N = getDnsChildren();
char *prg = getDnsProgram();
- int i;
+ int k;
int dnssocket;
static char fd_note_buf[FD_ASCII_NOTE_SZ];
- static int NChildrenAlloc = 0;
/* free old structures if present */
if (dns_child_table) {
- for (i = 0; i < NChildrenAlloc; i++)
- safe_free(dns_child_table[i]->ip_inbuf);
+ for (k = 0; k < NDnsServersAlloc; k++) {
+ safe_free(dns_child_table[k]->ip_inbuf);
+ safe_free(dns_child_table[k]);
+ }
safe_free(dns_child_table);
}
- dns_child_table = (dnsserver_entry **) xcalloc(N, sizeof(dnsserver_entry));
- NChildrenAlloc = N;
- dns_child_alive = 0;
+ dns_child_table = xcalloc(N, sizeof(dnsserver_t *));
+ NDnsServersAlloc = N;
debug(14, 1, "ipcacheOpenServers: Starting %d 'dns_server' processes\n", N);
- for (i = 0; i < N; i++) {
- dns_child_table[i] = (dnsserver_entry *) xcalloc(1, sizeof(dnsserver_entry));
+ for (k = 0; k < N; k++) {
+ dns_child_table[k] = xcalloc(1, sizeof(dnsserver_t));
if ((dnssocket = ipcache_create_dnsserver(prg)) < 0) {
debug(14, 1, "ipcacheOpenServers: WARNING: Cannot run 'dnsserver' process.\n");
debug(14, 1, " Fallling back to the blocking version.\n");
- dns_child_table[i]->alive = 0;
+ dns_child_table[k]->flags &= ~DNS_FLAG_ALIVE;
} else {
- dns_child_alive = 1;
- dns_child_table[i]->id = i;
- dns_child_table[i]->inpipe = dnssocket;
- dns_child_table[i]->outpipe = dnssocket;
- dns_child_table[i]->lastcall = squid_curtime;
- dns_child_table[i]->pending_count = 0;
- dns_child_table[i]->size = IP_INBUF - 1; /* spare one for \0 */
- dns_child_table[i]->offset = 0;
- dns_child_table[i]->alive = 1;
- dns_child_table[i]->ip_inbuf = (char *) xcalloc(1, IP_INBUF);
+ debug(14, 4, "ipcacheOpenServers: FD %d connected to %s #%d.\n",
+ dnssocket, prg, k + 1);
+ dns_child_table[k]->flags |= DNS_FLAG_ALIVE;
+ dns_child_table[k]->id = k + 1;
+ dns_child_table[k]->inpipe = dnssocket;
+ dns_child_table[k]->outpipe = dnssocket;
+ dns_child_table[k]->lastcall = squid_curtime;
+ dns_child_table[k]->size = IP_INBUF_SZ - 1; /* spare one for \0 */
+ dns_child_table[k]->offset = 0;
+ dns_child_table[k]->ip_inbuf = xcalloc(IP_INBUF_SZ, 1);
/* update fd_stat */
- sprintf(fd_note_buf, "%s #%d",
- prg,
- dns_child_table[i]->id);
- file_update_open(dns_child_table[i]->inpipe, fd_note_buf);
-
- debug(14, 5, "Calling fd_note() with FD %d and buf '%s'\n",
- dns_child_table[i]->inpipe, fd_note_buf);
-
- fd_note(dns_child_table[i]->inpipe, fd_note_buf);
- commSetNonBlocking(dns_child_table[i]->inpipe);
+ sprintf(fd_note_buf, "%s #%d", prg, dns_child_table[k]->id);
+ fd_note(dns_child_table[k]->inpipe, fd_note_buf);
+ commSetNonBlocking(dns_child_table[k]->inpipe);
/* clear unused handlers */
- comm_set_select_handler(dns_child_table[i]->inpipe,
+ comm_set_select_handler(dns_child_table[k]->inpipe,
COMM_SELECT_WRITE,
0,
0);
- comm_set_select_handler(dns_child_table[i]->outpipe,
+ comm_set_select_handler(dns_child_table[k]->outpipe,
COMM_SELECT_READ,
0,
0);
/* set handler for incoming result */
- comm_set_select_handler(dns_child_table[i]->inpipe,
+ comm_set_select_handler(dns_child_table[k]->inpipe,
COMM_SELECT_READ,
(PF) ipcache_dnsHandleRead,
- (void *) dns_child_table[i]);
- debug(14, 3, "ipcacheOpenServers: 'dns_server' %d started\n", i);
+ (void *) dns_child_table[k]);
+ debug(14, 3, "ipcacheOpenServers: 'dns_server' %d started\n", k);
}
}
}
debug(14, 3, "Initializing IP Cache...\n");
- last_dns_dispatched = getDnsChildren() - 1;
- if (!dns_error_message)
- dns_error_message = xcalloc(1, 256);
+ memset(&IpcacheStats, '\0', sizeof(IpcacheStats));
/* test naming lookup */
- if (!do_dns_test) {
+ if (!opt_dns_tests) {
debug(14, 4, "ipcache_init: Skipping DNS name lookup tests.\n");
} else if (!ipcache_testname()) {
fatal("ipcache_init: DNS name lookup tests failed/");
ip_table = hash_create(urlcmp, 229); /* small hash table */
/* init static area */
- static_result = (struct hostent *) xcalloc(1, sizeof(struct hostent));
+ static_result = xcalloc(1, sizeof(struct hostent));
static_result->h_length = 4;
/* Need a terminating NULL address (h_addr_list[1]) */
- static_result->h_addr_list = (char **) xcalloc(2, sizeof(char *));
- static_result->h_addr_list[0] = (char *) xcalloc(1, 4);
- static_result->h_name = (char *) xcalloc(1, MAX_HOST_NAME + 1);
+ static_result->h_addr_list = xcalloc(2, sizeof(char *));
+ static_result->h_addr_list[0] = xcalloc(1, 4);
+ static_result->h_name = xcalloc(1, MAX_HOST_NAME + 1);
ipcacheOpenServers();
char *name;
int fd;
{
- ipcache_entry *e;
- IpPending *p, *q;
-
- e = ipcache_get(name);
- if (!e) {
- /* not found any where */
- return 0;
- }
- /* look for matched fd */
- for (q = p = e->pending_head; p; q = p, p = p->next) {
- if (p->fd == fd) {
- break;
- }
- }
+ ipcache_entry *i = NULL;
+ struct _ip_pending *p = NULL;
+ int n = 0;
- if (p == NULL) {
- /* Can not find this ipcache_entry, weird */
- debug(14, 1, "ipcache_unregister: Failed to unregister FD %d from name: %s, can't find this FD.\n",
- fd, name);
+ debug(14, 3, "ipcache_unregister: FD %d, name '%s'\n", fd, name);
+ if ((i = ipcache_get(name)) == NULL)
return 0;
- }
- /* found */
- if (p == e->pending_head) {
- /* it's at the head of the queue */
- if (p->next) {
- /* there is something along the line */
- e->pending_head = p->next;
- safe_free(p->data);
- safe_free(p);
- } else {
- /* it is the only entry */
- e->pending_head = e->pending_tail = NULL;
- safe_free(p->data);
- safe_free(p);
+ if (i->status == IP_PENDING || i->status == IP_DISPATCHED) {
+ for (p = i->pending_head; p; p = p->next) {
+ if (p->fd == fd && p->handler != NULL) {
+ p->handler = NULL;
+ p->fd = -1;
+ n++;
+ }
}
- } else if (p == e->pending_tail) {
- /* it's at the tail */
- e->pending_tail = q;
- q->next = NULL;
- safe_free(p->data);
- safe_free(p);
- } else {
- /* it's in the middle */
- /* skip it in the list */
- q->next = p->next;
- safe_free(p->data);
- safe_free(p);
}
- return 1;
+ debug(14, 3, "ipcache_unregister: unregistered %d handlers\n", n);
+ return n;
}
-
-struct hostent *ipcache_gethostbyname(name)
+struct hostent *ipcache_gethostbyname(name, flags)
char *name;
+ int flags;
{
- ipcache_entry *result;
- unsigned int a1, a2, a3, a4;
- struct hostent *s_result = NULL;
-
- if (!name) {
- debug(14, 5, "ipcache_gethostbyname: Invalid argument?\n");
- return (NULL);
- }
- if (!(result = ipcache_get(name))) {
- /* cache miss */
- if (name) {
- debug(14, 5, "ipcache_gethostbyname: IPcache miss for '%s'.\n", name);
- }
- /* check if it's already a IP address in text form. */
- if (sscanf(name, "%u.%u.%u.%u", &a1, &a2, &a3, &a4) == 4) {
- *((unsigned long *) (void *) static_result->h_addr_list[0]) = inet_addr(name);
- strncpy(static_result->h_name, name, MAX_HOST_NAME);
- return static_result;
+ ipcache_entry *i = NULL;
+ struct hostent *hp = NULL;
+ unsigned int ip;
+
+ if (!name)
+ fatal_dump("ipcache_gethostbyname: NULL name");
+ IpcacheStats.requests++;
+ if ((i = ipcache_get(name))) {
+ if (i->status == IP_PENDING || i->status == IP_DISPATCHED) {
+ IpcacheStats.pending_hits++;
+ return NULL;
+ } else if (i->status == IP_NEGATIVE_CACHED) {
+ IpcacheStats.negative_hits++;
+ dns_error_message = i->error_message;
+ return NULL;
} else {
- s_result = gethostbyname(name);
+ IpcacheStats.hits++;
+ i->lastref = squid_curtime;
+ return &i->entry;
}
-
- if (s_result && s_result->h_name && (s_result->h_name[0] != '\0')) {
+ }
+ IpcacheStats.misses++;
+ /* check if it's already a IP address in text form. */
+ if ((ip = inet_addr(name)) != INADDR_NONE) {
+ *((u_num32 *) (void *) static_result->h_addr_list[0]) = ip;
+ strncpy(static_result->h_name, name, MAX_HOST_NAME);
+ return static_result;
+ }
+ if (flags & IP_BLOCKING_LOOKUP) {
+ IpcacheStats.ghbn_calls++;
+ hp = gethostbyname(name);
+ if (hp && hp->h_name && (hp->h_name[0] != '\0') && ip_table) {
/* good address, cached */
- debug(14, 10, "ipcache_gethostbyname: DNS success: cache for '%s'.\n", name);
- ipcache_add(name, ipcache_create(), s_result, 1);
- result = ipcache_get(name);
- return &(result->entry);
- } else {
- /* bad address, negative cached */
- debug(14, 3, "ipcache_gethostbyname: DNS failure: negative cache for '%s'.\n", name);
- ipcache_add(name, ipcache_create(), s_result, 0);
- return NULL;
+ ipcache_add(name, ipcache_create(), hp, 1);
+ i = ipcache_get(name);
+ return &i->entry;
}
-
+ /* bad address, negative cached */
+ if (ip_table)
+ ipcache_add(name, ipcache_create(), hp, 0);
+ return NULL;
}
- /* cache hit */
- debug(14, 5, "ipcache_gethostbyname: Hit for '%s'.\n", name ? name : "NULL");
- result->lastref = squid_curtime;
- return (result->status == CACHED) ? &(result->entry) : NULL;
+ if (flags & IP_LOOKUP_IF_MISS)
+ ipcache_nbgethostbyname(name, -1, dummy_handler, NULL);
+ return NULL;
}
-
/* process objects list */
-void stat_ipcache_get(sentry, obj)
+void stat_ipcache_get(sentry)
StoreEntry *sentry;
- cacheinfo *obj;
{
- char buffer[MAX_LINELEN];
- ipcache_entry *e = NULL;
- int i;
+ ipcache_entry *i = NULL;
+ int k;
int ttl;
- char status;
-
- sprintf(buffer, "{IP Cache Contents:\n\n");
- storeAppend(sentry, buffer, strlen(buffer));
-
- for (e = ipcache_GetFirst(); (e); e = ipcache_GetNext()) {
- if (e) {
- ttl = (e->ttl - squid_curtime + e->lastref);
- status = ipcache_status_char(e);
- if (status == 'P')
- ttl = 0;
-
- sprintf(buffer, " {%s %c %d %d",
- e->name, status, ttl, e->addr_count);
- storeAppend(sentry, buffer, strlen(buffer));
-
- for (i = 0; i < (int) e->addr_count; i++) {
- struct in_addr addr;
- memcpy((char *) &addr, e->entry.h_addr_list[i], e->entry.h_length);
- sprintf(buffer, " %s", inet_ntoa(addr));
- storeAppend(sentry, buffer, strlen(buffer));
- }
- for (i = 0; i < (int) e->alias_count; i++) {
- sprintf(buffer, " %s", e->entry.h_aliases[i]);
- storeAppend(sentry, buffer, strlen(buffer));
- }
- if (e->entry.h_name && strncmp(e->name, e->entry.h_name, MAX_LINELEN)) {
- sprintf(buffer, " %s", e->entry.h_name);
- storeAppend(sentry, buffer, strlen(buffer));
- }
- sprintf(buffer, "}\n");
- storeAppend(sentry, buffer, strlen(buffer));
- }
- }
- sprintf(buffer, "}\n");
- storeAppend(sentry, buffer, strlen(buffer));
-
-}
+ if (!ip_table)
+ return;
-char ipcache_status_char(e)
- ipcache_entry *e;
-{
- switch (e->status) {
- case CACHED:
- return ('C');
- case PENDING:
- return ('P');
- case NEGATIVE_CACHED:
- return ('N');
- default:
- debug(14, 1, "ipcache_status_char: unexpected IP cache status.\n");
+ storeAppendPrintf(sentry, "{IP Cache Statistics:\n");
+ storeAppendPrintf(sentry, "{IPcache Entries: %d}\n",
+ meta_data.ipcache_count);
+ storeAppendPrintf(sentry, "{IPcache Requests: %d}\n",
+ IpcacheStats.requests);
+ storeAppendPrintf(sentry, "{IPcache Hits: %d}\n",
+ IpcacheStats.hits);
+ storeAppendPrintf(sentry, "{IPcache Pending Hits: %d}\n",
+ IpcacheStats.pending_hits);
+ storeAppendPrintf(sentry, "{IPcache Negative Hits: %d}\n",
+ IpcacheStats.negative_hits);
+ storeAppendPrintf(sentry, "{IPcache Misses: %d}\n",
+ IpcacheStats.misses);
+ storeAppendPrintf(sentry, "{Blocking calls to gethostbyname(): %d}\n",
+ IpcacheStats.ghbn_calls);
+ storeAppendPrintf(sentry, "{dnsserver requests: %d}\n",
+ IpcacheStats.dnsserver_requests);
+ storeAppendPrintf(sentry, "{dnsserver replies: %d}\n",
+ IpcacheStats.dnsserver_replies);
+ storeAppendPrintf(sentry, "{dnsserver avg service time: %d msec}\n",
+ IpcacheStats.avg_svc_time);
+ storeAppendPrintf(sentry, "{number of dnsservers: %d}\n",
+ getDnsChildren());
+ storeAppendPrintf(sentry, "{dnsservers use histogram:}\n");
+ for (k = 0; k < getDnsChildren(); k++) {
+ storeAppendPrintf(sentry, "{ dnsserver #%d: %d}\n",
+ k + 1,
+ IpcacheStats.dnsserver_hist[k]);
}
- return ('X');
-}
-
-int ipcache_hash_entry_count()
-{
- ipcache_entry *e;
- int local_ip_count = 0;
-
- e = NULL;
-
- for (e = ipcache_GetFirst(); e; e = ipcache_GetNext()) {
- local_ip_count++;
+ storeAppendPrintf(sentry, "}\n\n");
+ storeAppendPrintf(sentry, "{IP Cache Contents:\n\n");
+
+ for (i = ipcache_GetFirst(); i; i = ipcache_GetNext()) {
+ if (i->status == IP_PENDING || i->status == IP_DISPATCHED)
+ ttl = 0;
+ else
+ ttl = (i->ttl - squid_curtime + i->lastref);
+ storeAppendPrintf(sentry, " {%-32.32s %c%c %6d %d",
+ i->name,
+ ipcache_status_char[i->status],
+ i->lock ? 'L' : ' ',
+ ttl,
+ i->addr_count);
+ for (k = 0; k < (int) i->addr_count; k++) {
+ struct in_addr addr;
+ xmemcpy(&addr, i->entry.h_addr_list[k], i->entry.h_length);
+ storeAppendPrintf(sentry, " %15s", inet_ntoa(addr));
+ }
+ for (k = 0; k < (int) i->alias_count; k++) {
+ storeAppendPrintf(sentry, " %s", i->entry.h_aliases[k]);
+ }
+ if (i->entry.h_name && strncmp(i->name, i->entry.h_name, MAX_LINELEN)) {
+ storeAppendPrintf(sentry, " %s", i->entry.h_name);
+ }
+ storeAppendPrintf(sentry, close_bracket);
}
-
- return local_ip_count;
+ storeAppendPrintf(sentry, close_bracket);
}
void ipcacheShutdownServers()
{
- dnsserver_entry *dns = NULL;
- int i;
+ dnsserver_t *dnsData = NULL;
+ int k;
static char *shutdown = "$shutdown\n";
debug(14, 3, "ipcacheShutdownServers:\n");
- for (i = 0; i < getDnsChildren(); i++) {
- dns = *(dns_child_table + i);
- debug(14, 3, "ipcacheShutdownServers: sending '$shutdown' to dnsserver #%d\n", i);
- debug(14, 3, "ipcacheShutdownServers: --> FD %d\n", dns->outpipe);
- file_write(dns->outpipe,
+ for (k = 0; k < getDnsChildren(); k++) {
+ dnsData = *(dns_child_table + k);
+ if (!(dnsData->flags & DNS_FLAG_ALIVE))
+ continue;
+ if (dnsData->flags & DNS_FLAG_BUSY)
+ continue;
+ if (dnsData->flags & DNS_FLAG_CLOSING)
+ continue;
+ debug(14, 3, "ipcacheShutdownServers: sending '$shutdown' to dnsserver #%d\n", dnsData->id);
+ debug(14, 3, "ipcacheShutdownServers: --> FD %d\n", dnsData->outpipe);
+ comm_write(dnsData->outpipe,
xstrdup(shutdown),
strlen(shutdown),
- 0, /* Lock */
- 0, /* Handler */
- 0); /* Handler-data */
+ 0, /* timeout */
+ NULL, /* Handler */
+ NULL); /* Handler-data */
+ dnsData->flags |= DNS_FLAG_CLOSING;
}
}
+
+static int dummy_handler(u1, u2, u3)
+ int u1;
+ struct hostent *u2;
+ void *u3;
+{
+ return 0;
+}
+
+void ipcacheLockEntry(name)
+ char *name;
+{
+ ipcache_entry *i;
+ if ((i = ipcache_get(name)) == NULL)
+ return;
+ i->lock++;
+}
+
+static int ipcacheHasPending(i)
+ ipcache_entry *i;
+{
+ struct _ip_pending *p = NULL;
+ if (i->status != IP_PENDING)
+ return 0;
+ for (p = i->pending_head; p; p = p->next)
+ if (p->handler)
+ return 1;
+ return 0;
+}
-/* $Id: main.cc,v 1.46 1996/05/03 22:56:29 wessels Exp $ */
-
-/* DEBUG: Section 1 main: startup and main loop */
+/*
+ * $Id: main.cc,v 1.47 1996/07/09 03:41:32 wessels Exp $
+ *
+ * DEBUG: section 1 Startup and Main Loop
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include "squid.h"
time_t squid_starttime = 0;
time_t next_cleaning = 0;
-int theAsciiConnection = -1;
-int theUdpConnection = -1;
+int theHttpConnection = -1;
+int theInIcpConnection = -1;
+int theOutIcpConnection = -1;
int do_reuse = 1;
int opt_unlink_on_reload = 0;
+int opt_reload_hit_only = 0; /* only UDP_HIT during store relaod */
int catch_signals = 1;
-int do_dns_test = 1;
+int opt_dns_tests = 1;
+int opt_foreground_rebuild = 0;
int vhost_mode = 0;
int unbuffered_logs = 1; /* debug and hierarhcy unbuffered by default */
int shutdown_pending = 0; /* set by SIGTERM handler (shut_down()) */
int reread_pending = 0; /* set by SIGHUP handler */
-char *version_string = SQUID_VERSION;
-char *appname = "squid";
-
-extern void (*failure_notify) (); /* for error reporting from xmalloc */
-
-static int asciiPortNumOverride = 0;
-static int udpPortNumOverride = 0;
+char version_string[] = SQUID_VERSION;
+char appname[] = "squid";
+char localhost[] = "127.0.0.1";
+struct in_addr local_addr;
+
+/* for error reporting from xmalloc and friends */
+extern void (*failure_notify) _PARAMS((char *));
+
+static int rotate_pending = 0; /* set by SIGUSR1 handler */
+static int httpPortNumOverride = 1;
+static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
+#if MALLOC_DBG
static int malloc_debug_level = 0;
+#endif
+static void rotate_logs _PARAMS((int));
+static void reconfigure _PARAMS((int));
static void usage()
{
fprintf(stderr, "\
-Usage: %s [-Rsehvz] [-f config-file] [-[apu] port]\n\
+Usage: %s [-hsvzCDFRUVY] [-f config-file] [-[au] port]\n\
+ -a port Specify ASCII port number (default: %d).\n\
+ -f file Use given config-file instead of\n\
+ %s\n\
-h Print help message.\n\
-s Enable logging to syslog.\n\
+ -u port Specify UDP port number (default: %d), disable with 0.\n\
-v Print version.\n\
-z Zap disk storage -- deletes all objects in disk cache.\n\
-C Do not catch fatal signals.\n\
-D Disable initial DNS tests.\n\
+ -F Foreground fast store rebuild.\n\
-R Do not set REUSEADDR on port.\n\
-U Unlink expired objects on reload.\n\
- -f file Use given config-file instead of\n\
- %s\n\
- -a port Specify ASCII port number (default: %d).\n\
- -u port Specify UDP port number (default: %d).\n",
- appname, DefaultConfigFile, CACHE_HTTP_PORT, CACHE_ICP_PORT);
+ -V Virtual host httpd-accelerator.\n\
+ -Y Only return UDP_HIT or UDP_DENIED during fast store reload.\n",
+ appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
exit(1);
}
extern char *optarg;
int c;
- while ((c = getopt(argc, argv, "vCDRVUbsif:a:p:u:m:zh?")) != -1) {
+ while ((c = getopt(argc, argv, "CDFRUVYa:bf:hm:su:vz?")) != -1) {
switch (c) {
- case 'v':
- printf("Squid Cache: Version %s\n", version_string);
- exit(0);
- /* NOTREACHED */
- case 'b':
- unbuffered_logs = 0;
- break;
- case 'V':
- vhost_mode = 1;
- break;
case 'C':
catch_signals = 0;
break;
case 'D':
- do_dns_test = 0;
+ opt_dns_tests = 0;
break;
- case 's':
- syslog_enable = 0;
+ case 'F':
+ opt_foreground_rebuild = 1;
break;
case 'R':
do_reuse = 0;
case 'U':
opt_unlink_on_reload = 1;
break;
+ case 'V':
+ vhost_mode = 1;
+ break;
+ case 'Y':
+ opt_reload_hit_only = 1;
+ break;
+ case 'a':
+ httpPortNumOverride = atoi(optarg);
+ break;
+ case 'b':
+ unbuffered_logs = 0;
+ break;
case 'f':
xfree(ConfigFile);
ConfigFile = xstrdup(optarg);
break;
- case 'a':
- asciiPortNumOverride = atoi(optarg);
- break;
- case 'u':
- udpPortNumOverride = atoi(optarg);
+ case 'h':
+ usage();
break;
case 'm':
+#if MALLOC_DBG
malloc_debug_level = atoi(optarg);
break;
+#else
+ fatal("Need to add -DMALLOC_DBG when compiling to use -m option");
+#endif
+ case 's':
+ syslog_enable = 0;
+ break;
+ case 'u':
+ icpPortNumOverride = atoi(optarg);
+ if (icpPortNumOverride < 0)
+ icpPortNumOverride = 0;
+ break;
+ case 'v':
+ printf("Squid Cache: Version %s\n", version_string);
+ exit(0);
+ /* NOTREACHED */
case 'z':
zap_disk_store = 1;
break;
case '?':
- case 'h':
default:
usage();
break;
}
}
+void rotate_logs(sig)
+ int sig;
+{
+ debug(21, 1, "rotate_logs: SIGUSR1 received.\n");
+ rotate_pending = 1;
+#if !HAVE_SIGACTION
+ signal(sig, rotate_logs);
+#endif
+}
+
+void reconfigure(sig)
+ int sig;
+{
+ debug(21, 1, "reconfigure: SIGHUP received\n");
+ debug(21, 1, "Waiting %d seconds for active connections to finish\n",
+ getShutdownLifetime());
+ reread_pending = 1;
+#if !HAVE_SIGACTION
+ signal(sig, reconfigure);
+#endif
+}
+
+void shut_down(sig)
+ int sig;
+{
+ debug(21, 1, "Preparing for shutdown after %d connections\n",
+ ntcpconn + nudpconn);
+ debug(21, 1, "Waiting %d seconds for active connections to finish\n",
+ getShutdownLifetime());
+ shutdown_pending = 1;
+}
+
void serverConnectionsOpen()
{
+ struct in_addr addr;
+ u_short port;
/* Get our real priviliges */
- get_suid();
/* Open server ports */
- theAsciiConnection = comm_open(COMM_NONBLOCKING,
- getAsciiPortNum(),
- 0,
- "Ascii Port");
- if (theAsciiConnection < 0) {
- fatal("Cannot open ascii Port");
+ enter_suid();
+ theHttpConnection = comm_open(COMM_NONBLOCKING,
+ getTcpIncomingAddr(),
+ getHttpPortNum(),
+ "HTTP Port");
+ leave_suid();
+ if (theHttpConnection < 0) {
+ fatal("Cannot open HTTP Port");
}
- fd_note(theAsciiConnection, "HTTP (Ascii) socket");
- comm_listen(theAsciiConnection);
- comm_set_select_handler(theAsciiConnection,
+ fd_note(theHttpConnection, "HTTP socket");
+ comm_listen(theHttpConnection);
+ comm_set_select_handler(theHttpConnection,
COMM_SELECT_READ,
asciiHandleConn,
0);
- debug(1, 1, "Accepting HTTP (ASCII) connections on FD %d.\n",
- theAsciiConnection);
+ debug(1, 1, "Accepting HTTP connections on FD %d.\n",
+ theHttpConnection);
if (!httpd_accel_mode || getAccelWithProxy()) {
- if (getUdpPortNum() > -1) {
- theUdpConnection = comm_open(COMM_NONBLOCKING | COMM_DGRAM,
- getUdpPortNum(),
- 0,
- "Ping Port");
- if (theUdpConnection < 0)
- fatal("Cannot open UDP Port");
- fd_note(theUdpConnection, "ICP (UDP) socket");
- comm_set_select_handler(theUdpConnection,
+ if ((port = getIcpPortNum()) > 0) {
+ theInIcpConnection = comm_open(COMM_NONBLOCKING | COMM_DGRAM,
+ getUdpIncomingAddr(),
+ port,
+ "ICP Port");
+ if (theInIcpConnection < 0)
+ fatal("Cannot open ICP Port");
+ fd_note(theInIcpConnection, "ICP socket");
+ comm_set_select_handler(theInIcpConnection,
COMM_SELECT_READ,
icpHandleUdp,
0);
- debug(1, 1, "Accepting ICP (UDP) connections on FD %d.\n",
- theUdpConnection);
+ debug(1, 1, "Accepting ICP connections on FD %d.\n",
+ theInIcpConnection);
+
+ if ((addr = getUdpOutgoingAddr()).s_addr != INADDR_NONE) {
+ theOutIcpConnection = comm_open(COMM_NONBLOCKING | COMM_DGRAM,
+ addr,
+ port,
+ "ICP Port");
+ if (theOutIcpConnection < 0)
+ fatal("Cannot open Outgoing ICP Port");
+ comm_set_select_handler(theOutIcpConnection,
+ COMM_SELECT_READ,
+ icpHandleUdp,
+ 0);
+ debug(1, 1, "Accepting ICP connections on FD %d.\n",
+ theOutIcpConnection);
+ fd_note(theOutIcpConnection, "Outgoing ICP socket");
+ fd_note(theInIcpConnection, "Incoming ICP socket");
+ } else {
+ theOutIcpConnection = theInIcpConnection;
+ }
}
}
- /* And restore our priviliges to normal */
- check_suid();
}
void serverConnectionsClose()
{
- if (theAsciiConnection >= 0) {
- debug(21, 1, "FD %d Closing Ascii connection\n",
- theAsciiConnection);
- comm_close(theAsciiConnection);
- comm_set_select_handler(theAsciiConnection,
+ /* NOTE, this function will be called repeatedly while shutdown
+ * is pending */
+ if (theHttpConnection >= 0) {
+ debug(21, 1, "FD %d Closing HTTP connection\n",
+ theHttpConnection);
+ comm_close(theHttpConnection);
+ comm_set_select_handler(theHttpConnection,
COMM_SELECT_READ,
NULL,
0);
- theAsciiConnection = -1;
+ theHttpConnection = -1;
}
- if (theUdpConnection >= 0) {
- debug(21, 1, "FD %d Closing Udp connection\n",
- theUdpConnection);
- /* Dont actually close it, just disable the read handler */
- /* so we can still transmit while shutdown pending */
- /* comm_close(theUdpConnection); */
- comm_set_select_handler(theUdpConnection,
+ if (theInIcpConnection >= 0) {
+ /* NOTE, don't close outgoing ICP connection, we need to write to
+ * it during shutdown */
+ debug(21, 1, "FD %d Closing ICP connection\n",
+ theInIcpConnection);
+ if (theInIcpConnection != theOutIcpConnection)
+ comm_close(theInIcpConnection);
+ comm_set_select_handler(theInIcpConnection,
COMM_SELECT_READ,
NULL,
0);
- /* theUdpConnection = -1; */
+ if (theInIcpConnection != theOutIcpConnection)
+ comm_set_select_handler(theOutIcpConnection,
+ COMM_SELECT_READ,
+ NULL,
+ 0);
+ theInIcpConnection = -1;
}
}
neighborsDestroy();
parseConfigFile(ConfigFile);
- _db_init(getCacheLogFile());
+ _db_init(getCacheLogFile(), getDebugOptions());
neighbors_init();
ipcacheOpenServers();
serverConnectionsOpen();
(void) ftpInitialize();
- if (theUdpConnection >= 0 && (!httpd_accel_mode || getAccelWithProxy()))
- neighbors_open(theUdpConnection);
+ if (theOutIcpConnection >= 0 && (!httpd_accel_mode || getAccelWithProxy()))
+ neighbors_open(theOutIcpConnection);
debug(1, 0, "Ready to serve requests.\n");
}
static void mainInitialize()
{
static int first_time = 1;
-
if (catch_signals) {
- signal(SIGSEGV, death);
- signal(SIGBUS, death);
+ squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
+ squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
}
- signal(SIGPIPE, SIG_IGN);
- signal(SIGCHLD, sig_child);
+ squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
+ squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
if (ConfigFile == NULL)
ConfigFile = xstrdup(DefaultConfigFile);
parseConfigFile(ConfigFile);
- if (asciiPortNumOverride > 0)
- setAsciiPortNum(asciiPortNumOverride);
- if (udpPortNumOverride > 0)
- setUdpPortNum(udpPortNumOverride);
+ leave_suid(); /* Run as non privilegied user */
- _db_init(getCacheLogFile());
- fdstat_open(fileno(debug_log), LOG);
+ if (httpPortNumOverride != 1)
+ setHttpPortNum((u_short) httpPortNumOverride);
+ if (icpPortNumOverride != 1)
+ setIcpPortNum((u_short) icpPortNumOverride);
+
+ _db_init(getCacheLogFile(), getDebugOptions());
+ fdstat_open(fileno(debug_log), FD_LOG);
fd_note(fileno(debug_log), getCacheLogFile());
- debug(1, 0, "Starting Squid Cache (version %s)...\n", version_string);
- debug(1, 1, "With %d file descriptors available\n", getMaxFD());
+ debug(1, 0, "Starting Squid Cache version %s for %s...\n",
+ version_string,
+ CONFIG_HOST_TYPE);
+ debug(1, 1, "With %d file descriptors available\n", FD_SETSIZE);
if (first_time) {
disk_init(); /* disk_init must go before ipcache_init() */
- writePidFile(); /* write PID file before setuid() */
+ writePidFile(); /* write PID file */
}
ipcache_init();
neighbors_init();
(void) ftpInitialize();
-#if defined(MALLOC_DBG)
+#if MALLOC_DBG
malloc_debug(0, malloc_debug_level);
#endif
- /* do suid checking */
- check_suid();
-
if (first_time) {
first_time = 0;
/* module initialization */
do_mallinfo = 1;
}
serverConnectionsOpen();
- if (theUdpConnection >= 0 && (!httpd_accel_mode || getAccelWithProxy()))
- neighbors_open(theUdpConnection);
-
- signal(SIGUSR1, rotate_logs);
- signal(SIGHUP, reconfigure);
- signal(SIGTERM, shut_down);
- signal(SIGINT, shut_down);
-
+ if (theOutIcpConnection >= 0 && (!httpd_accel_mode || getAccelWithProxy()))
+ neighbors_open(theOutIcpConnection);
+
+ squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
+ squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
+ squid_signal(SIGHUP, reconfigure, SA_RESTART);
+ squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
+ squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
debug(1, 0, "Ready to serve requests.\n");
}
time_t last_announce = 0;
time_t loop_delay;
+ memset(&local_addr, '\0', sizeof(struct in_addr));
+ local_addr.s_addr = inet_addr(localhost);
+
errorInitialize();
squid_starttime = getCurrentTime();
setMaxFD();
- for (n = getMaxFD(); n > 2; n--)
- close(n);
+ if (catch_signals)
+ for (n = FD_SETSIZE; n > 2; n--)
+ close(n);
#if HAVE_MALLOPT
- /* set malloc option */
- /* use small block algorithm for faster allocation */
- /* grain of small block */
+#ifdef M_GRAIN
+ /* Round up all sizes to a multiple of this */
mallopt(M_GRAIN, 16);
+#endif
+#ifdef M_MXFAST
/* biggest size that is considered a small block */
- mallopt(M_MXFAST, 4096);
- /* number of holding small block */
- mallopt(M_NLBLKS, 100);
+ mallopt(M_MXFAST, 256);
#endif
+#ifdef M_NBLKS
+ /* allocate this many small blocks at once */
+ mallopt(M_NLBLKS, 32);
+#endif
+#endif /* HAVE_MALLOPT */
/*init comm module */
comm_init();
/* we have to init fdstat here. */
fdstat_init(PREOPEN_FD);
- fdstat_open(0, LOG);
- fdstat_open(1, LOG);
- fdstat_open(2, LOG);
+ fdstat_open(0, FD_LOG);
+ fdstat_open(1, FD_LOG);
+ fdstat_open(2, FD_LOG);
fd_note(0, "STDIN");
fd_note(1, "STDOUT");
fd_note(2, "STDERR");
if (getCleanRate() > 0)
next_cleaning = time(NULL) + getCleanRate();
for (;;) {
- loop_delay = (time_t) 60;
+ loop_delay = (time_t) 10;
/* maintain cache storage */
if (squid_curtime > last_maintain) {
storeMaintainSwapSpace();
last_maintain = squid_curtime;
}
+ if (rotate_pending) {
+ ftpServerClose();
+ _db_rotate_log(); /* cache.log */
+ storeWriteCleanLog();
+ storeRotateLog(); /* store.log */
+ neighbors_rotate_log(); /* hierarchy.log */
+ stat_rotate_log(); /* access.log */
+ (void) ftpInitialize();
+ rotate_pending = 0;
+ }
/* do background processing */
if (doBackgroundProcessing())
loop_delay = (time_t) 0;
fatal_dump("Select Loop failed!");
break;
case COMM_TIMEOUT:
- /* this happens after 1 minute of idle time, or
- * when next_cleaning has arrived */
- /* garbage collection */
if (getCleanRate() > 0 && squid_curtime >= next_cleaning) {
debug(1, 1, "Performing a garbage collection...\n");
n = storePurgeOld();
break;
case COMM_SHUTDOWN:
/* delayed close so we can transmit while shutdown pending */
- if (theUdpConnection > 0) {
- comm_close(theUdpConnection);
- theUdpConnection = -1;
+ if (theOutIcpConnection > 0) {
+ comm_close(theOutIcpConnection);
+ theOutIcpConnection = -1;
}
if (shutdown_pending) {
normal_shutdown();
-
-/* $Id: mime.cc,v 1.12 1996/04/16 05:05:25 wessels Exp $ */
+/*
+ * $Id: mime.cc,v 1.13 1996/07/09 03:41:33 wessels Exp $
+ *
+ * DEBUG: section 25 MIME Parsing
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
/*
- * DEBUG: Section 25 mime
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
return NULL;
}
-int mime_refresh_request(mime)
- char *mime;
+/* need to take the lowest, non-zero pointer to the end of the headers.
+ * The headers end at the first empty line */
+char *mime_headers_end(char *mime)
{
- char *pr = NULL;
- if (mime == NULL)
+ char *p1, *p2;
+ char *end = NULL;
+
+ p1 = strstr(mime, "\r\n\r\n");
+ p2 = strstr(mime, "\n\n");
+
+ if (p1 && p2)
+ end = p1 < p2 ? p1 : p2;
+ else
+ end = p1 ? p1 : p2;
+ if (end)
+ end += (end == p1 ? 4 : 2);
+
+ return end;
+}
+
+int mime_headers_size(char *mime)
+{
+ char *end;
+
+ end = mime_headers_end(mime);
+
+ if (end)
+ return end - mime;
+ else
return 0;
- if (mime_get_header(mime, "If-Modified-Since"))
- return 1;
- if ((pr = mime_get_header(mime, "pragma"))) {
- if (strcasecmp(pr, "no-cache"))
- return 1;
- }
- return 0;
}
ext_table_entry *mime_ext_to_type(extension)
* returns non-zero on error, or 0 on success.
*/
int mk_mime_hdr(result, ttl, size, lmt, type)
- char *result, *type;
+ char *result;
+ char *type;
int size;
- time_t ttl, lmt;
+ time_t ttl;
+ time_t lmt;
{
time_t expiretime;
time_t t;
static char date[100];
- static char expire[100];
- static char last_modified_time[100];
+ static char expires[100];
+ static char last_modified[100];
+ static char content_length[100];
if (result == NULL)
return 1;
-
t = squid_curtime;
- expiretime = t + ttl;
-
- date[0] = expire[0] = last_modified_time[0] = result[0] = '\0';
- strncpy(date, mkrfc850(&t), 100);
- strncpy(expire, mkrfc850(&expiretime), 100);
- strncpy(last_modified_time, mkrfc850(&lmt), 100);
-
- sprintf(result, "Content-Type: %s\r\nContent-Size: %d\r\nDate: %s\r\nExpires: %s\r\nLast-Modified-Time: %s\r\n", type, size, date, expire, last_modified_time);
+ expiretime = ttl ? t + ttl : 0;
+ date[0] = expires[0] = last_modified[0] = '\0';
+ content_length[0] = result[0] = '\0';
+ sprintf(date, "Date: %s\r\n", mkrfc850(&t));
+ if (ttl >= 0)
+ sprintf(expires, "Expires: %s\r\n", mkrfc850(&expiretime));
+ if (lmt)
+ sprintf(last_modified, "Last-Modified: %s\r\n", mkrfc850(&lmt));
+ if (size > 0)
+ sprintf(content_length, "Content-Length: %d\r\n", size);
+ sprintf(result, "Server: %s/%s\r\n%s%s%sContent-Type: %s\r\n%s",
+ appname,
+ version_string,
+ date,
+ expires,
+ last_modified,
+ type,
+ content_length);
return 0;
}
-/* $Id: neighbors.cc,v 1.23 1996/05/01 22:36:35 wessels Exp $ */
-
-/* TODO:
- * - change 'neighbor' to 'sibling'
- * - change 'edge' to neighbor?
- * - make ->flags structure
- * - fix "can't continue" if DNS lookup for neighbor fails.
+/*
+ * $Id: neighbors.cc,v 1.24 1996/07/09 03:41:33 wessels Exp $
+ *
+ * DEBUG: section 15 Neighbor Routines
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
*/
/*
- * DEBUG: Section 15 neighbors:
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
-static neighbors *friends = NULL;
+static int edgeWouldBePinged _PARAMS((edge *, request_t *));
+static void neighborRemove _PARAMS((edge *));
+static neighbors *friends = NULL;
static struct neighbor_cf *Neighbor_cf = NULL;
-
static icp_common_t echo_hdr;
-static short echo_port;
+static u_short echo_port;
+static struct in_addr any_addr;
+
FILE *cache_hierarchy_log = NULL;
-static char *hier_strings[] =
+char *hier_strings[] =
{
"NONE",
"DIRECT",
"NEIGHBOR_HIT",
"PARENT_HIT",
"SINGLE_PARENT",
+ "FIRST_UP_PARENT",
"NO_PARENT_DIRECT",
"FIRST_PARENT_MISS",
"LOCAL_IP_DIRECT",
+ "FIREWALL_IP_DIRECT",
"DEAD_PARENT",
"DEAD_NEIGHBOR",
"REVIVE_PARENT",
"REVIVE_NEIGHBOR",
"NO_DIRECT_FAIL",
"SOURCE_FASTEST",
+ "UDP_HIT_OBJ",
"INVALID CODE"
};
struct sockaddr_in *from;
{
int j;
- int port;
+ u_short port;
struct in_addr ip;
edge *e = NULL;
for (e = friends->edges_head; e; e = e->next) {
for (j = 0; j < e->n_addresses; j++) {
- if (ip.s_addr == e->addresses[j].s_addr && port == e->udp_port) {
+ if (ip.s_addr == e->addresses[j].s_addr && port == e->icp_port) {
return e;
}
}
fflush(cache_hierarchy_log);
}
-static int edgeWouldBePinged(e, host)
+static int edgeWouldBePinged(e, request)
edge *e;
- char *host;
+ request_t *request;
{
- int offset;
dom_list *d = NULL;
int do_ping = 1;
+ struct _acl_list *a = NULL;
- if (e->domains == NULL)
+ if (e->domains == NULL && e->acls == NULL)
return do_ping;
-
do_ping = 0;
for (d = e->domains; d; d = d->next) {
- if ((offset = strlen(host) - strlen(d->domain)) < 0) {
- do_ping = !d->do_ping;
- continue;
- }
- if (strcasecmp(d->domain, host + offset) == 0) {
- /* found a match, no need to check any more domains */
- do_ping = d->do_ping;
- break;
- } else {
- do_ping = !d->do_ping;
- }
+ if (matchDomainName(d->domain, request->host))
+ return d->do_ping;
+ do_ping = !d->do_ping;
+ }
+ for (a = e->acls; a; a = a->next) {
+ if (aclMatchAcl(a->acl,
+ any_addr, /* bogus */
+ request->method,
+ request->protocol,
+ request->host,
+ request->port,
+ request->urlpath))
+ return a->op;
+ do_ping = !a->op;
}
return do_ping;
}
-edge *getSingleParent(host, n)
- char *host;
+edge *getSingleParent(request, n)
+ request_t *request;
int *n;
{
edge *p = NULL;
if (n == NULL && friends->n_parent < 1)
return NULL;
for (e = friends->edges_head; e; e = e->next) {
- if (edgeWouldBePinged(e, host)) {
+ if (edgeWouldBePinged(e, request)) {
count++;
if (e->type != EDGE_PARENT) {
/* we matched a neighbor, not a parent. There
return NULL;
}
-edge *getFirstParent(host)
- char *host;
+edge *getFirstUpParent(request)
+ request_t *request;
{
edge *e = NULL;
if (friends->n_parent < 1)
return NULL;
for (e = friends->edges_head; e; e = e->next) {
+ if (!e->neighbor_up)
+ continue;
if (e->type != EDGE_PARENT)
continue;
- if (edgeWouldBePinged(e, host))
+ if (edgeWouldBePinged(e, request))
return e;
}
return NULL;
return friends->edges_head;
}
+void neighborRemove(target)
+ edge *target;
+{
+ edge *e = NULL;
+ edge **E = NULL;
+ e = friends->edges_head;
+ E = &friends->edges_head;
+ while (e) {
+ if (target == e)
+ break;
+ E = &e->next;
+ e = e->next;
+ }
+ if (e) {
+ *E = e->next;
+ safe_free(e);
+ }
+}
+
void neighborsDestroy()
{
edge *e = NULL;
for (e = friends->edges_head; e; e = next) {
next = e->next;
safe_free(e->host);
+ /* XXX I think we need to free e->domains too -DW */
safe_free(e);
}
safe_free(friends);
int fd;
{
int j;
- struct sockaddr_in our_socket_name;
+ struct sockaddr_in name;
struct sockaddr_in *ap;
- int sock_name_length = sizeof(our_socket_name);
+ int len = sizeof(struct sockaddr_in);
char **list = NULL;
edge *e = NULL;
+ edge *next = NULL;
+ edge **E = NULL;
struct in_addr *ina = NULL;
+ struct servent *sep = NULL;
- if (getsockname(fd, (struct sockaddr *) &our_socket_name,
- &sock_name_length) == -1) {
- debug(15, 1, "getsockname(%d,%p,%p) failed.\n",
- fd, &our_socket_name, &sock_name_length);
- }
+ memset(&name, '\0', sizeof(struct sockaddr_in));
+ if (getsockname(fd, (struct sockaddr *) &name, &len) < 0)
+ debug(15, 1, "getsockname(%d,%p,%p) failed.\n", fd, &name, &len);
friends->fd = fd;
/* Prepare neighbor connections, one at a time */
- for (e = friends->edges_head; e; e = e->next) {
+ E = &friends->edges_head;
+ next = friends->edges_head;
+ while ((e = next)) {
+ next = e->next;
debug(15, 2, "Finding IP addresses for '%s'\n", e->host);
if ((list = getAddressList(e->host)) == NULL) {
- sprintf(tmp_error_buf, "DNS lookup for '%s' failed! Cannot continue.\n",
- e->host);
- fatal(tmp_error_buf);
+ debug(0, 0, "WARNING!!: DNS lookup for '%s' failed!\n", e->host);
+ debug(0, 0, "THIS NEIGHBOR WILL BE IGNORED.\n");
+ *E = next; /* skip */
+ safe_free(e);
+ continue;
}
+ ipcacheLockEntry(e->host);
e->n_addresses = 0;
for (j = 0; *list && j < EDGE_MAX_ADDRESSES; j++) {
ina = &e->addresses[j];
- memcpy(&(ina->s_addr), *list, 4);
+ xmemcpy(&(ina->s_addr), *list, 4);
list++;
e->n_addresses++;
}
if (e->n_addresses < 1) {
- sprintf(tmp_error_buf, "No IP addresses found for '%s'; Cannot continue.\n", e->host);
- fatal(tmp_error_buf);
+ debug(0, 0, "WARNING!!: No IP address found for '%s'!\n", e->host);
+ debug(0, 0, "THIS NEIGHBOR WILL BE IGNORED.\n");
+ *E = next; /* skip */
+ safe_free(e);
+ continue;
}
for (j = 0; j < e->n_addresses; j++) {
- debug(15, 2, "--> IP address #%d: %s\n", j, inet_ntoa(e->addresses[j]));
+ debug(15, 2, "--> IP address #%d: %s\n",
+ j, inet_ntoa(e->addresses[j]));
}
- e->rtt = 1000;
+ e->stats.rtt = 0;
/* Prepare query packet for future use */
e->header.opcode = ICP_OP_QUERY;
e->header.version = ICP_VERSION_CURRENT;
e->header.length = 0;
e->header.reqnum = 0;
- memset(e->header.auth, '\0', sizeof(u_num32) * ICP_AUTH_SIZE);
- e->header.shostid = our_socket_name.sin_addr.s_addr;
+ e->header.flags = 0;
+ e->header.pad = 0;
+ /* memset(e->header.auth, '\0', sizeof(u_num32) * ICP_AUTH_SIZE); */
+ e->header.shostid = name.sin_addr.s_addr;
ap = &e->in_addr;
memset(ap, '\0', sizeof(struct sockaddr_in));
ap->sin_family = AF_INET;
ap->sin_addr = e->addresses[0];
- ap->sin_port = htons(e->udp_port);
+ ap->sin_port = htons(e->icp_port);
if (e->type == EDGE_PARENT) {
debug(15, 3, "parent_install: host %s addr %s port %d\n",
e->host, inet_ntoa(ap->sin_addr),
- e->udp_port);
+ e->icp_port);
e->neighbor_up = 1;
} else {
debug(15, 3, "neighbor_install: host %s addr %s port %d\n",
e->host, inet_ntoa(ap->sin_addr),
- e->udp_port);
+ e->icp_port);
e->neighbor_up = 1;
}
+ E = &e->next;
+ }
- /* do this only the first time thru */
- if (0 == echo_hdr.opcode) {
- struct servent *sep;
-
- echo_hdr.opcode = ICP_OP_SECHO;
- echo_hdr.version = ICP_VERSION_CURRENT;
- echo_hdr.length = 0;
- echo_hdr.reqnum = 0;
- memset(echo_hdr.auth, '\0', sizeof(u_num32) * ICP_AUTH_SIZE);
- echo_hdr.shostid = our_socket_name.sin_addr.s_addr;
-
- sep = getservbyname("echo", "udp");
- echo_port = sep ? ntohs((u_short) sep->s_port) : 7;
- }
+ if (0 == echo_hdr.opcode) {
+ echo_hdr.opcode = ICP_OP_SECHO;
+ echo_hdr.version = ICP_VERSION_CURRENT;
+ echo_hdr.length = 0;
+ echo_hdr.reqnum = 0;
+ echo_hdr.flags = 0;
+ echo_hdr.pad = 0;
+ /* memset(echo_hdr.auth, '\0', sizeof(u_num32) * ICP_AUTH_SIZE); */
+ echo_hdr.shostid = name.sin_addr.s_addr;
+ sep = getservbyname("echo", "udp");
+ echo_port = sep ? ntohs((u_short) sep->s_port) : 7;
}
}
struct sockaddr_in to_addr;
edge *e = NULL;
int i;
- MemObject *m = entry->mem_obj;
+ MemObject *mem = entry->mem_obj;
- m->e_pings_n_pings = 0;
- m->e_pings_n_acks = 0;
- m->e_pings_first_miss = NULL;
- m->w_rtt = 0;
- m->start_ping = current_time;
+ mem->e_pings_n_pings = 0;
+ mem->e_pings_n_acks = 0;
+ mem->e_pings_first_miss = NULL;
+ mem->w_rtt = 0;
+ mem->start_ping = current_time;
if (friends->edges_head == (edge *) NULL)
return 0;
/* Don't resolve refreshes through neighbors because we don't resolve
* misses through neighbors */
- if ((e->type == EDGE_SIBLING) && (entry->flag & REFRESH_REQUEST))
+ if (e->type == EDGE_SIBLING && entry->flag & REFRESH_REQUEST)
continue;
- /* skip dumb caches where we failed to connect() w/in the last 60s */
- if (e->udp_port == echo_port &&
- (squid_curtime - e->last_fail_time < 60))
+ /* skip any cache where we failed to connect() w/in the last 60s */
+ if (squid_curtime - e->last_fail_time < 60)
continue;
- if (!edgeWouldBePinged(e, host))
+ if (!edgeWouldBePinged(e, proto->request))
continue; /* next edge */
+ if (e->options & NEIGHBOR_NO_QUERY)
+ continue;
debug(15, 4, "neighborsUdpPing: pinging cache %s for <URL:%s>\n",
e->host, url);
debug(15, 3, "neighborsUdpPing: key = '%s'\n", entry->key);
debug(15, 3, "neighborsUdpPing: reqnum = %d\n", e->header.reqnum);
- if (e->udp_port == echo_port) {
+ if (e->icp_port == echo_port) {
debug(15, 4, "neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n");
- icpUdpSend(friends->fd, url, &echo_hdr, &e->in_addr, ICP_OP_DECHO);
+ icpUdpSend(friends->fd, url, &echo_hdr, &e->in_addr, ICP_OP_DECHO, LOG_TAG_NONE);
} else {
- icpUdpSend(friends->fd, url, &e->header, &e->in_addr, ICP_OP_QUERY);
+ icpUdpSend(friends->fd, url, &e->header, &e->in_addr, ICP_OP_QUERY, LOG_TAG_NONE);
}
- e->ack_deficit++;
- e->num_pings++;
- e->pings_sent++;
+ e->stats.ack_deficit++;
+ e->stats.pings_sent++;
- if (e->ack_deficit < HIER_MAX_DEFICIT) {
+ if (e->stats.ack_deficit < HIER_MAX_DEFICIT) {
/* consider it's alive. count it */
e->neighbor_up = 1;
- m->e_pings_n_pings++;
+ mem->e_pings_n_pings++;
} else {
/* consider it's dead. send a ping but don't count it. */
e->neighbor_up = 0;
- if (e->ack_deficit > (HIER_MAX_DEFICIT << 1))
+ if (e->stats.ack_deficit > (HIER_MAX_DEFICIT << 1))
/* do this to prevent wrap around but we still want it
* to move a bit so we can debug it easier. */
- e->ack_deficit = HIER_MAX_DEFICIT + 1;
+ e->stats.ack_deficit = HIER_MAX_DEFICIT + 1;
debug(15, 6, "cache %s is considered dead but send PING anyway, hope it comes up soon.\n",
inet_ntoa(e->in_addr.sin_addr));
/* log it once at the threshold */
- if ((e->ack_deficit == HIER_MAX_DEFICIT)) {
+ if ((e->stats.ack_deficit == HIER_MAX_DEFICIT)) {
if (e->type == EDGE_SIBLING) {
hierarchy_log_append("Detect: ",
HIER_DEAD_NEIGHBOR, 0,
/* only do source_ping if we have neighbors */
if (echo_hdr.opcode) {
- if (proto->source_ping && (hep = ipcache_gethostbyname(host))) {
+ if (proto->source_ping && (hep = ipcache_gethostbyname(host, IP_BLOCKING_LOOKUP))) {
debug(15, 6, "neighborsUdpPing: Send to original host\n");
debug(15, 6, "neighborsUdpPing: url=%s, host=%s, t=%d\n",
url, host, t);
to_addr.sin_family = AF_INET;
- memcpy(&to_addr.sin_addr, hep->h_addr, hep->h_length);
- to_addr.sin_port = echo_port;
+ xmemcpy(&to_addr.sin_addr, hep->h_addr, hep->h_length);
+ to_addr.sin_port = htons(echo_port);
echo_hdr.reqnum = squid_curtime;
debug(15, 6, "neighborsUdpPing - url: %s to url-host %s \n",
url, inet_ntoa(to_addr.sin_addr));
/* send to original site */
- icpUdpSend(friends->fd, url, &echo_hdr, &to_addr, ICP_OP_SECHO);
+ icpUdpSend(friends->fd, url, &echo_hdr, &to_addr, ICP_OP_SECHO, LOG_TAG_NONE);
} else {
debug(15, 6, "neighborsUdpPing: Source Ping is disabled.\n");
}
}
- return (m->e_pings_n_pings);
+ return (mem->e_pings_n_pings);
}
*
* If a hit process is already started, then sobeit
*/
-void neighborsUdpAck(fd, url, header, from, entry)
+void neighborsUdpAck(fd, url, header, from, entry, data, data_sz)
int fd;
char *url;
icp_common_t *header;
struct sockaddr_in *from;
StoreEntry *entry;
+ char *data;
+ int data_sz;
{
edge *e = NULL;
- MemObject *m = entry->mem_obj;
+ MemObject *mem = entry->mem_obj;
int w_rtt;
+ int rtt;
+ int n;
+ HttpStateData *httpState = NULL;
debug(15, 6, "neighborsUdpAck: url=%s (%d chars), header=0x%x, from=0x%x, ent=0x%x\n",
url, strlen(url), header, from, entry);
if (e) {
/* reset the deficit. It's alive now. */
/* Don't care about exact count. */
- if ((e->ack_deficit >= HIER_MAX_DEFICIT)) {
+ if ((e->stats.ack_deficit >= HIER_MAX_DEFICIT)) {
if (e->type == EDGE_SIBLING) {
hierarchy_log_append("Detect: ",
HIER_REVIVE_NEIGHBOR, 0, e->host);
HIER_REVIVE_PARENT, 0, e->host);
}
}
- e->ack_deficit = 0;
e->neighbor_up = 1;
- e->pings_acked++;
+ e->stats.ack_deficit = 0;
+ n = ++e->stats.pings_acked;
+ if (header->opcode < ICP_OP_END)
+ e->stats.counts[header->opcode]++;
+ if (mem) {
+ if (n > RTT_AV_FACTOR)
+ n = RTT_AV_FACTOR;
+ rtt = tvSubMsec(mem->start_ping, current_time);
+ e->stats.rtt = (e->stats.rtt * (n - 1) + rtt) / n;
+ }
}
/* check if someone is already fetching it */
- if (BIT_TEST(entry->flag, ENTRY_DISPATCHED) || (entry->ping_status != WAITING)) {
- if (entry->ping_status == DONE) {
+ if (BIT_TEST(entry->flag, ENTRY_DISPATCHED) || (entry->ping_status != PING_WAITING)) {
+ if (entry->ping_status == PING_DONE) {
debug(15, 5, "There is already a cache/source dispatched for this object\n");
debug(15, 5, "--> <URL:%s>\n", entry->url);
debug(15, 5, "--> entry->flag & ENTRY_DISPATCHED = %d\n",
HIER_SOURCE_FASTEST,
0,
inet_ntoa(from->sin_addr));
+ if (mem)
+ mem->hierarchy_code = HIER_SOURCE_FASTEST;
BIT_SET(entry->flag, ENTRY_DISPATCHED);
- entry->ping_status = DONE;
+ entry->ping_status = PING_DONE;
getFromCache(0, entry, NULL, entry->mem_obj->request);
}
return;
- }
- if (header->opcode == ICP_OP_HIT) {
+ } else if (header->opcode == ICP_OP_HIT_OBJ) {
+ if (entry->object_len != 0) {
+ debug(15, 0, "Too late UDP_HIT_OBJ '%s'?\n", entry->url);
+ return;
+ }
+ protoCancelTimeout(0, entry);
+ entry->ping_status = PING_DONE;
+ httpState = xcalloc(1, sizeof(HttpStateData));
+ httpState->entry = entry;
+ httpProcessReplyHeader(httpState, data, data_sz);
+ storeAppend(entry, data, data_sz);
+ storeComplete(entry);
+ hierarchy_log_append(entry->url,
+ HIER_UDP_HIT_OBJ,
+ 0,
+ e ? e->host : inet_ntoa(from->sin_addr));
+ if (mem)
+ mem->hierarchy_code = HIER_UDP_HIT_OBJ;
+ if (httpState->reply_hdr)
+ put_free_8k_page(httpState->reply_hdr);
+ safe_free(httpState);
+ return;
+ } else if (header->opcode == ICP_OP_HIT) {
/* If an edge is not found, count it as a MISS message. */
if (!e) {
/* count it as a MISS message */
- m->e_pings_n_acks++;
+ mem->e_pings_n_acks++;
return;
}
/* GOT a HIT here */
debug(15, 6, "HIT: Getting %s from host: %s\n", entry->url, e->host);
if (e->type == EDGE_SIBLING) {
hierarchy_log_append(entry->url, HIER_NEIGHBOR_HIT, 0, e->host);
+ if (mem)
+ mem->hierarchy_code = HIER_NEIGHBOR_HIT;
} else {
hierarchy_log_append(entry->url, HIER_PARENT_HIT, 0, e->host);
+ if (mem)
+ mem->hierarchy_code = HIER_PARENT_HIT;
}
BIT_SET(entry->flag, ENTRY_DISPATCHED);
- entry->ping_status = DONE;
+ entry->ping_status = PING_DONE;
getFromCache(0, entry, e, entry->mem_obj->request);
- e->hits++;
return;
} else if ((header->opcode == ICP_OP_MISS) || (header->opcode == ICP_OP_DECHO)) {
/* everytime we get here, count it as a miss */
- m->e_pings_n_acks++;
- if (e)
- e->misses++;
+ mem->e_pings_n_acks++;
if (header->opcode == ICP_OP_DECHO) {
/* receive ping back from non-ICP cache */
inet_ntoa(e->in_addr.sin_addr));
if (e->type == EDGE_PARENT) {
- w_rtt = tvSubMsec(m->start_ping, current_time) / e->weight;
- if (m->w_rtt == 0 || w_rtt < m->w_rtt) {
+ w_rtt = tvSubMsec(mem->start_ping, current_time) / e->weight;
+ if (mem->w_rtt == 0 || w_rtt < mem->w_rtt) {
debug(15, 6, "Dumb-cache has minimum weighted RTT = %d\n", w_rtt);
- m->e_pings_first_miss = e;
- m->w_rtt = w_rtt;
+ mem->e_pings_first_miss = e;
+ mem->w_rtt = w_rtt;
}
} else {
debug(15, 6, "Dumb Cached as a neighbor does not make sense.\n");
} else if (e && e->type == EDGE_PARENT) {
/* ICP_OP_MISS from a cache */
- w_rtt = tvSubMsec(m->start_ping, current_time) / e->weight;
- if (m->w_rtt == 0 || w_rtt < m->w_rtt) {
- m->e_pings_first_miss = e;
- m->w_rtt = w_rtt;
+ w_rtt = tvSubMsec(mem->start_ping, current_time) / e->weight;
+ if (mem->w_rtt == 0 || w_rtt < mem->w_rtt) {
+ mem->e_pings_first_miss = e;
+ mem->w_rtt = w_rtt;
}
}
- if (m->e_pings_n_acks == m->e_pings_n_pings) {
+ if (mem->e_pings_n_acks == mem->e_pings_n_pings) {
BIT_SET(entry->flag, ENTRY_DISPATCHED);
- entry->ping_status = DONE;
+ entry->ping_status = PING_DONE;
debug(15, 6, "Receive MISSes from all neighbors and parents\n");
/* pass in fd=0 here so getFromCache() looks up the real FD
* and resets the timeout handler */
getFromDefaultSource(0, entry);
return;
}
+ } else if (header->opcode == ICP_OP_DENIED) {
+ debug(15, 5, "neighborsUdpAck: Access denied for '%s'\n", entry->url);
+ if (e && e->stats.pings_acked > 100) {
+ if (100 * e->stats.counts[ICP_OP_DENIED] / e->stats.pings_acked > 95) {
+ debug(15, 0, "95%% of replies from '%s' are UDP_DENIED\n", e->host);
+ debug(15, 0, "Disabling '%s', please check your configuration.\n", e->host);
+ neighborRemove(e);
+ }
+ }
} else {
debug(15, 0, "neighborsUdpAck: WHY ARE WE HERE? header->opcode = %d\n",
header->opcode);
}
}
-void neighbors_cf_add(host, type, ascii_port, udp_port, proxy_only, weight)
+void neighbors_cf_add(host, type, http_port, icp_port, options, weight)
char *host;
char *type;
- int ascii_port;
- int udp_port;
- int proxy_only;
+ int http_port;
+ int icp_port;
+ int options;
int weight;
{
struct neighbor_cf *t, *u;
- t = (struct neighbor_cf *) xcalloc(sizeof(struct neighbor_cf), 1);
+ t = xcalloc(1, sizeof(struct neighbor_cf));
t->host = xstrdup(host);
t->type = xstrdup(type);
- t->ascii_port = ascii_port;
- t->udp_port = udp_port;
- t->proxy_only = proxy_only;
+ t->http_port = http_port;
+ t->icp_port = icp_port;
+ t->options = options;
t->weight = weight;
t->next = (struct neighbor_cf *) NULL;
}
}
-int neighbors_cf_domain(host, domain)
+void neighbors_cf_domain(host, domain)
char *host;
char *domain;
{
- struct neighbor_cf *t;
- dom_list *l;
- dom_list **L;
+ struct neighbor_cf *t = NULL;
+ dom_list *l = NULL;
+ dom_list **L = NULL;
for (t = Neighbor_cf; t; t = t->next) {
if (strcmp(t->host, host) == 0)
break;
}
-
- if (t == NULL)
- return 0;
-
- l = (dom_list *) xmalloc(sizeof(dom_list));
+ if (t == NULL) {
+ debug(15, 0, "%s, line %d: No cache_host '%s'\n",
+ cfg_filename, config_lineno, host);
+ return;
+ }
+ l = xmalloc(sizeof(dom_list));
l->do_ping = 1;
if (*domain == '!') { /* check for !.edu */
l->do_ping = 0;
l->next = NULL;
for (L = &(t->domains); *L; L = &((*L)->next));
*L = l;
+}
+
+void neighbors_cf_acl(host, aclname)
+ char *host;
+ char *aclname;
+{
+ struct neighbor_cf *t = NULL;
+ struct _acl_list *L = NULL;
+ struct _acl_list **Tail = NULL;
+ struct _acl *a = NULL;
- return 1;
+ for (t = Neighbor_cf; t; t = t->next) {
+ if (strcmp(t->host, host) == 0)
+ break;
+ }
+ if (t == NULL) {
+ debug(15, 0, "%s, line %d: No cache_host '%s'\n",
+ cfg_filename, config_lineno, host);
+ return;
+ }
+ L = xcalloc(1, sizeof(struct _acl_list));
+ L->op = 1;
+ if (*aclname == '!') {
+ L->op = 0;
+ aclname++;
+ }
+ debug(15, 3, "neighbors_cf_acl: looking for ACL name '%s'\n", aclname);
+ a = aclFindByName(aclname);
+ if (a == NULL) {
+ debug(15, 0, "%s line %d: %s\n",
+ cfg_filename, config_lineno, config_input_line);
+ debug(15, 0, "neighbors_cf_acl: ACL name '%s' not found.\n", aclname);
+ xfree(L);
+ return;
+ }
+ if (a->type == ACL_SRC_IP) {
+ debug(15, 0, "%s line %d: %s\n",
+ cfg_filename, config_lineno, config_input_line);
+ debug(15, 0, "neighbors_cf_acl: 'src' ALC's not supported for 'cache_host_acl'\n");
+ xfree(L);
+ return;
+ }
+ L->acl = a;
+ for (Tail = &(t->acls); *Tail; Tail = &((*Tail)->next));
+ *Tail = L;
}
void neighbors_init()
debug(15, 1, "neighbors_init: Initializing Neighbors...\n");
if (friends == NULL)
- friends = (neighbors *) xcalloc(1, sizeof(neighbors));
+ friends = xcalloc(1, sizeof(neighbors));
if ((fname = getHierarchyLogFile()))
neighborsOpenLog(fname);
for (t = Neighbor_cf; t; t = next) {
next = t->next;
- if (!strcmp(t->host, me) && t->ascii_port == getAsciiPortNum()) {
+ if (!strcmp(t->host, me) && t->http_port == getHttpPortNum()) {
debug(15, 0, "neighbors_init: skipping cache_host %s %s %d %d\n",
- t->type, t->host, t->ascii_port, t->udp_port);
+ t->type, t->host, t->http_port, t->icp_port);
continue;
}
- debug(15, 1, "Adding a %s: %s\n", t->type, t->host);
+ debug(15, 1, "Adding a %s: %s/%d/%d\n",
+ t->type, t->host, t->http_port, t->icp_port);
- e = (edge *) xcalloc(1, sizeof(edge));
- e->ascii_port = t->ascii_port;
- e->udp_port = t->udp_port;
- e->proxy_only = t->proxy_only;
+ e = xcalloc(1, sizeof(edge));
+ e->http_port = t->http_port;
+ e->icp_port = t->icp_port;
+ e->options = t->options;
e->weight = t->weight;
e->host = t->host;
e->domains = t->domains;
+ e->acls = t->acls;
e->neighbor_up = 1;
if (!strcmp(t->type, "parent")) {
friends->n_parent++;
friends->n_neighbor++;
e->type = EDGE_SIBLING;
}
+ safe_free(t->type);
/* Append edge */
if (!friends->edges_head)
safe_free(t);
}
Neighbor_cf = NULL;
+ any_addr.s_addr = inet_addr("0.0.0.0");
}
void neighbors_rotate_log()
-/* $Id: recv-announce.cc,v 1.4 1996/04/16 16:35:29 wessels Exp $ */
+/*
+ * $Id: recv-announce.cc,v 1.5 1996/07/09 03:41:36 wessels Exp $
+ *
+ * DEBUG: section 0 Announement Server
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
+ */
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netdb.h>
+#include <unistd.h>
+#include <signal.h>
#define RECV_BUF_SIZE 8192
int len;
struct hostent *hp = NULL;
char logfile[BUFSIZ];
- char *t = NULL;
char ip[4];
for (len = 0; len < 32; len++) {
perror("recv");
exit(2);
}
- memcpy(ip, &R.sin_addr.s_addr, 4);
+ xmemcpy(ip, &R.sin_addr.s_addr, 4);
hp = gethostbyaddr(ip, 4, AF_INET);
printf("==============================================================================\n");
printf("Received from %s [%s]\n",
fputs(buf, stdout);
fflush(stdout);
}
+ return 0;
}
--- /dev/null
+/*
+ * $Id: redirect.cc,v 1.2 1996/07/09 03:41:37 wessels Exp $
+ *
+ * DEBUG: section 29 Redirector
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "squid.h"
+
+#define REDIRECT_FLAG_ALIVE 0x01
+#define REDIRECT_FLAG_BUSY 0x02
+#define REDIRECT_FLAG_CLOSING 0x04
+
+typedef void (*RH) _PARAMS((int, char *));
+
+
+typedef struct {
+ int fd;
+ char *orig_url;
+ RH handler;
+} redirectStateData;
+
+typedef struct _redirector {
+ int index;
+ int flags;
+ int fd;
+ char *inbuf;
+ unsigned int size;
+ unsigned int offset;
+ redirectStateData *redirectState;
+} redirector_t;
+
+struct redirectQueueData {
+ struct redirectQueueData *next;
+ redirectStateData *redirectState;
+};
+
+static redirector_t *GetFirstAvailable _PARAMS((void));
+static int redirectCreateRedirector _PARAMS((char *command));
+static int redirectHandleRead _PARAMS((int, redirector_t *));
+static redirectStateData *Dequeue _PARAMS(());
+static void Enqueue _PARAMS((redirectStateData *));
+static void redirectDispatch _PARAMS((redirector_t *, redirectStateData *));
+
+
+static redirector_t **redirect_child_table = NULL;
+static int NRedirectors = 0;
+static struct redirectQueueData *redirectQueueHead = NULL;
+static struct redirectQueueData **redirectQueueTailP = &redirectQueueHead;
+
+/* TCP SOCKET VERSION */
+int redirectCreateRedirector(command)
+ char *command;
+{
+ int pid;
+ u_short port;
+ struct sockaddr_in S;
+ static int n_redirector = 0;
+ int cfd;
+ int sfd;
+ int len;
+ int fd;
+ cfd = comm_open(COMM_NOCLOEXEC,
+ local_addr,
+ 0,
+ "socket to redirector");
+ if (cfd == COMM_ERROR) {
+ debug(14, 0, "redirect_create_redirector: Failed to create redirector\n");
+ return -1;
+ }
+ len = sizeof(S);
+ memset(&S, '\0', len);
+ if (getsockname(cfd, (struct sockaddr *) &S, &len) < 0) {
+ debug(14, 0, "redirect_create_redirector: getsockname: %s\n", xstrerror());
+ comm_close(cfd);
+ return -1;
+ }
+ port = ntohs(S.sin_port);
+ debug(14, 4, "redirect_create_redirector: bind to local host.\n");
+ listen(cfd, 1);
+ if ((pid = fork()) < 0) {
+ debug(14, 0, "redirect_create_redirector: fork: %s\n", xstrerror());
+ comm_close(cfd);
+ return -1;
+ }
+ if (pid > 0) { /* parent */
+ comm_close(cfd); /* close shared socket with child */
+ /* open new socket for parent process */
+ sfd = comm_open(0, local_addr, 0, NULL); /* blocking! */
+ if (sfd == COMM_ERROR)
+ return -1;
+ if (comm_connect(sfd, localhost, port) == COMM_ERROR) {
+ comm_close(sfd);
+ return -1;
+ }
+ comm_set_fd_lifetime(sfd, -1);
+ debug(14, 4, "redirect_create_redirector: FD %d connected to %s #%d.\n",
+ sfd, command, n_redirector);
+ return sfd;
+ }
+ /* child */
+ no_suid(); /* give up extra priviliges */
+ dup2(cfd, 3);
+ for (fd = FD_SETSIZE; fd > 3; fd--)
+ close(fd);
+ execlp(command, "(redirector)", "-t", NULL);
+ debug(14, 0, "redirect_create_redirector: %s: %s\n", command, xstrerror());
+ _exit(1);
+ return 0;
+}
+
+
+
+int redirectHandleRead(fd, redirector)
+ int fd;
+ redirector_t *redirector;
+{
+ int len;
+ redirectStateData *r = redirector->redirectState;
+ char *t = NULL;
+
+ len = read(fd,
+ redirector->inbuf + redirector->offset,
+ redirector->size - redirector->offset);
+ debug(14, 5, "redirectHandleRead: Result from Redirector %d.\n",
+ redirector->index + 1);
+ if (len <= 0) {
+ debug(14, redirector->flags & REDIRECT_FLAG_CLOSING ? 5 : 1,
+ "FD %d: Connection from Redirector #%d is closed, disabling\n",
+ fd, redirector->index + 1);
+ redirector->flags = 0;
+ comm_close(fd);
+ return 0;
+ }
+ redirector->offset += len;
+ redirector->inbuf[redirector->offset] = '\0';
+ /* reschedule */
+ comm_set_select_handler(redirector->fd,
+ COMM_SELECT_READ,
+ (PF) redirectHandleRead,
+ redirector);
+ if ((t = strchr(redirector->inbuf, '\n'))) {
+ /* end of record found */
+ *t = '\0';
+ if (t == redirector->inbuf)
+ r->handler(r->fd, r->orig_url);
+ else
+ r->handler(r->fd, redirector->inbuf);
+ redirector->redirectState = NULL;
+ redirector->flags &= ~REDIRECT_FLAG_BUSY;
+ }
+ while ((r = Dequeue()) && (redirector = GetFirstAvailable()))
+ redirectDispatch(redirector, r);
+ return 0;
+}
+
+void redirectStart(url, fd, handler)
+ char *url;
+ int fd;
+ RH handler;
+{
+ redirectStateData *r = NULL;
+ redirector_t *redirector = NULL;
+
+ if (!handler)
+ fatal_dump("redirectStart: NULL handler");
+ r = xcalloc(1, sizeof(redirectStateData));
+ r->fd = fd;
+ r->orig_url = url;
+ r->handler = handler;
+ if ((redirector = GetFirstAvailable()))
+ redirectDispatch(redirector, r);
+ else
+ Enqueue(r);
+}
+
+static void Enqueue(r)
+ redirectStateData *r;
+{
+ struct redirectQueueData *new = xcalloc(1, sizeof(struct redirectQueueData));
+ new->redirectState = r;
+ *redirectQueueTailP = new;
+ redirectQueueTailP = &new->next;
+}
+
+static redirectStateData *Dequeue()
+{
+ struct redirectQueueData *old = NULL;
+ redirectStateData *r = NULL;
+ if (redirectQueueHead) {
+ r = redirectQueueHead->redirectState;
+ old = redirectQueueHead;
+ redirectQueueHead = redirectQueueHead->next;
+ if (redirectQueueHead == NULL)
+ redirectQueueTailP = &redirectQueueHead;
+ safe_free(old);
+ }
+ return r;
+}
+
+static redirector_t *GetFirstAvailable()
+{
+ int k;
+ redirector_t *redirect = NULL;
+ for (k = 0; k < NRedirectors; k++) {
+ redirect = *(redirect_child_table + k);
+ if (!(redirect->flags & REDIRECT_FLAG_BUSY))
+ return redirect;
+ }
+ return NULL;
+}
+
+
+static void redirectDispatch(redirect, r)
+ redirector_t *redirect;
+ redirectStateData *r;
+{
+ char *buf = NULL;
+ redirect->flags |= REDIRECT_FLAG_BUSY;
+ redirect->redirectState = r;
+ comm_write(redirect->fd,
+ xstrdup(buf),
+ strlen(buf),
+ 0, /* timeout */
+ NULL, /* Handler */
+ NULL); /* Handler-data */
+ debug(14, 5, "redirectDispatch: Request sent to Redirector #%d.\n",
+ redirect->index + 1);
+}
+
+
+void redirectOpenServers()
+{
+ char *prg = getRedirectProgram();
+ int k;
+ int redirectsocket;
+ static char fd_note_buf[FD_ASCII_NOTE_SZ];
+
+ /* free old structures if present */
+ if (redirect_child_table) {
+ for (k = 0; k < NRedirectors; k++)
+ safe_free(redirect_child_table[k]);
+ safe_free(redirect_child_table);
+ }
+ NRedirectors = getRedirectChildren();
+ redirect_child_table = xcalloc(NRedirectors, sizeof(redirector_t *));
+ debug(14, 1, "redirectOpenServers: Starting %d '%s' processes\n",
+ NRedirectors, prg);
+ for (k = 0; k < NRedirectors; k++) {
+ redirect_child_table[k] = xcalloc(1, sizeof(redirector_t));
+ if ((redirectsocket = redirectCreateRedirector(prg)) < 0) {
+ debug(14, 1, "WARNING: Cannot run '%s' process.\n", prg);
+ redirect_child_table[k]->flags &= ~REDIRECT_FLAG_ALIVE;
+ } else {
+ redirect_child_table[k]->flags |= REDIRECT_FLAG_ALIVE;
+ redirect_child_table[k]->index = k;
+ redirect_child_table[k]->fd = redirectsocket;
+ sprintf(fd_note_buf, "%s #%d",
+ prg,
+ redirect_child_table[k]->index + 1);
+ fd_note(redirect_child_table[k]->fd, fd_note_buf);
+ commSetNonBlocking(redirect_child_table[k]->fd);
+
+ /* set handler for incoming result */
+ comm_set_select_handler(redirect_child_table[k]->fd,
+ COMM_SELECT_READ,
+ (PF) redirectHandleRead,
+ (void *) redirect_child_table[k]);
+ debug(14, 3, "redirectOpenServers: 'redirect_server' %d started\n",
+ k);
+ }
+ }
+}
+
+int redirectUnregister(url, fd)
+ char *url;
+ int fd;
+{
+ return 0;
+}
+
+void redirectShutdownServers()
+{
+ redirector_t *redirector = NULL;
+ int k;
+ static char *shutdown = "$shutdown\n";
+
+ debug(14, 3, "redirectShutdownServers:\n");
+
+ for (k = 0; k < getRedirectChildren(); k++) {
+ redirector = *(redirect_child_table + k);
+ debug(14, 3, "redirectShutdownServers: sending '$shutdown' to redirector #%d\n", k);
+ debug(14, 3, "redirectShutdownServers: --> FD %d\n", redirector->fd);
+ comm_write(redirector->fd,
+ xstrdup(shutdown),
+ strlen(shutdown),
+ 0, /* timeout */
+ NULL, /* Handler */
+ NULL); /* Handler-data */
+ redirector->flags |= REDIRECT_FLAG_CLOSING;
+ }
+}
-/* $Id: send-announce.cc,v 1.11 1996/05/01 22:36:36 wessels Exp $ */
-
/*
- * DEBUG: Section 27 send-announce
+ * $Id: send-announce.cc,v 1.12 1996/07/09 03:41:37 wessels Exp $
+ *
+ * DEBUG: section 27 Cache Announcer
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
*/
#include "squid.h"
-
void send_announce()
{
static char tbuf[256];
struct hostent *hp = NULL;
char *host = NULL;
char *file = NULL;
- int port;
+ u_short port;
int fd;
int l;
int n;
host = getAnnounceHost();
port = getAnnouncePort();
- if ((hp = ipcache_gethostbyname(host)) == NULL) {
+ if ((hp = ipcache_gethostbyname(host, IP_BLOCKING_LOOKUP)) == NULL) {
debug(27, 1, "send_announce: Unknown host '%s'\n", host);
return;
}
strcat(sndbuf, tbuf);
sprintf(tbuf, "Running on %s %d %d\n",
getMyHostname(),
- getAsciiPortNum(),
- getUdpPortNum());
+ getHttpPortNum(),
+ getIcpPortNum());
strcat(sndbuf, tbuf);
if (getAdminEmail()) {
sprintf(tbuf, "cache_admin: %s\n", getAdminEmail());
debug(27, 1, "send_announce: %s: %s\n", file, xstrerror());
}
}
- qdata = (icpUdpData *) xcalloc(1, sizeof(icpUdpData));
+ qdata = xcalloc(1, sizeof(icpUdpData));
qdata->msg = xstrdup(sndbuf);
qdata->len = strlen(sndbuf) + 1;
qdata->address.sin_family = AF_INET;
qdata->address.sin_port = htons(port);
- memcpy(&qdata->address.sin_addr, hp->h_addr_list[0], hp->h_length);
+ xmemcpy(&qdata->address.sin_addr, hp->h_addr_list[0], hp->h_length);
AppendUdp(qdata);
- comm_set_select_handler(theUdpConnection,
+ comm_set_select_handler(theOutIcpConnection,
COMM_SELECT_WRITE,
(PF) icpUdpReply,
(void *) qdata);
/*
- * $Id: squid.h,v 1.22 1996/07/08 22:42:53 wessels Exp $
+ * $Id: squid.h,v 1.23 1996/07/09 03:41:39 wessels Exp $
*
* AUTHOR: Duane Wessels
*
extern char appname[]; /* main.c */
extern struct in_addr local_addr; /* main.c */
extern char localhost[];
+extern struct in_addr any_addr; /* comm.c */
/* Prototypes and definitions which don't really deserve a seaprate
/*
- * $Id: ssl.cc,v 1.2 1996/05/03 22:56:31 wessels Exp $
+ * $Id: ssl.cc,v 1.3 1996/07/09 03:41:39 wessels Exp $
*
- * DEBUG: Section 26 ssl
+ * DEBUG: section 26 Secure Sockets Layer Proxy
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
*/
-#include "squid.h"
-#define SSL_BUFSIZ (1<<14)
+#include "squid.h"
typedef struct {
char *url;
static void sslWriteServer _PARAMS((int fd, SslStateData * sslState));
static void sslWriteClient _PARAMS((int fd, SslStateData * sslState));
static void sslConnected _PARAMS((int fd, SslStateData * sslState));
+static int sslConnect _PARAMS((int fd, struct hostent *, SslStateData *));
static void sslConnInProgress _PARAMS((int fd, SslStateData * sslState));
+static void sslErrorComplete _PARAMS((int, char *, int, int, void *));
+static void sslClose _PARAMS((SslStateData * sslState));
+static int sslClientClosed _PARAMS((int fd, SslStateData * sslState));
+
+static void sslClose(sslState)
+ SslStateData *sslState;
+{
+ if (sslState->client.fd > -1) {
+ /* remove the "unexpected" client close handler */
+ comm_remove_close_handler(sslState->client.fd,
+ (PF) sslClientClosed,
+ (void *) sslState);
+ comm_close(sslState->client.fd);
+ sslState->client.fd = -1;
+ }
+ if (sslState->server.fd > -1) {
+ comm_close(sslState->server.fd);
+ }
+}
+
+/* This is called only if the client connect closes unexpectedly,
+ * ie from icpDetectClientClose() */
+static int sslClientClosed(fd, sslState)
+ int fd;
+ SslStateData *sslState;
+{
+ debug(26, 3, "sslClientClosed: FD %d\n", fd);
+ /* we have been called from comm_close for the client side, so
+ * just need to clean up the server side */
+ comm_close(sslState->server.fd);
+ return 0;
+}
static int sslStateFree(fd, sslState)
int fd;
safe_free(sslState->server.buf);
safe_free(sslState->client.buf);
xfree(sslState->url);
+ requestUnlink(sslState->request);
memset(sslState, '\0', sizeof(SslStateData));
safe_free(sslState);
return 0;
{
debug(26, 4, "sslLifeTimeExpire: FD %d: URL '%s'>\n",
fd, sslState->url);
- comm_close(sslState->client.fd); /* close client first */
- comm_close(sslState->server.fd);
+ sslClose(sslState);
}
/* Read from server side and queue it for writing to the client */
SslStateData *sslState;
{
int len;
- len = read(sslState->server.fd, sslState->server.buf, 4096);
+ len = read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF);
debug(26, 5, "sslReadServer FD %d, read %d bytes\n", fd, len);
if (len < 0) {
debug(26, 1, "sslReadServer: FD %d: read failure: %s\n",
(void *) sslState,
sslState->timeout);
} else {
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
}
} else if (len == 0) {
/* Connection closed; retrieval done. */
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
} else {
sslState->server.offset = 0;
sslState->server.len = len;
SslStateData *sslState;
{
int len;
- len = read(sslState->client.fd, sslState->client.buf, 4096);
+ len = read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF);
debug(26, 5, "sslReadClient FD %d, read %d bytes\n",
sslState->client.fd, len);
if (len < 0) {
(void *) sslState,
sslState->timeout);
} else {
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
}
} else if (len == 0) {
/* Connection closed; retrieval done. */
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
} else {
sslState->client.offset = 0;
sslState->client.len = len;
if (len < 0) {
debug(26, 2, "sslWriteServer: FD %d: write failure: %s.\n",
sslState->server.fd, xstrerror());
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
return;
}
if ((sslState->client.offset += len) >= sslState->client.len) {
if (len < 0) {
debug(26, 2, "sslWriteClient: FD %d: write failure: %s.\n",
sslState->client.fd, xstrerror());
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
return;
}
if (sslState->size_ptr)
int fd;
SslStateData *sslState;
{
- if (fd != sslState->server.fd)
- fatal_dump("sslReadTimeout: FD mismatch!\n");
debug(26, 3, "sslReadTimeout: FD %d\n", fd);
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
}
static void sslConnected(fd, sslState)
COMM_SELECT_WRITE,
(PF) sslWriteClient,
(void *) sslState);
- comm_set_fd_lifetime(fd, -1); /* disable lifetime */
+ comm_set_fd_lifetime(fd, 86400); /* extend lifetime */
comm_set_select_handler_plus_timeout(sslState->server.fd,
COMM_SELECT_TIMEOUT,
(PF) sslReadTimeout,
(void *) sslState);
}
+static void sslErrorComplete(fd, buf, size, errflag, sslState)
+ int fd;
+ char *buf;
+ int size;
+ int errflag;
+ void *sslState;
+{
+ safe_free(buf);
+ sslClose(sslState);
+}
+
static void sslConnInProgress(fd, sslState)
int fd;
SslStateData *sslState;
{
request_t *req = sslState->request;
+ char *buf = NULL;
debug(26, 5, "sslConnInProgress: FD %d sslState=%p\n", fd, sslState);
if (comm_connect(fd, req->host, req->port) != COMM_OK) {
- debug(26, 5, "sslConnInProgress: FD %d: %s", fd, xstrerror());
+ debug(26, 5, "sslConnInProgress: FD %d: %s\n", fd, xstrerror());
switch (errno) {
#if EINPROGRESS != EALREADY
case EINPROGRESS:
(void *) sslState);
return;
default:
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ buf = squid_error_url(sslState->url,
+ METHOD_CONNECT,
+ ERR_CONNECT_FAIL,
+ NULL,
+ 500,
+ xstrerror());
+ comm_write(sslState->client.fd,
+ xstrdup(buf),
+ strlen(buf),
+ 30,
+ sslErrorComplete,
+ sslState);
return;
}
}
return;
}
-
-int sslStart(fd, url, request, mime_hdr, size_ptr)
+static int sslConnect(fd, hp, sslState)
int fd;
- char *url;
- request_t *request;
- char *mime_hdr;
- int *size_ptr;
+ struct hostent *hp;
+ SslStateData *sslState;
{
- /* Create state structure. */
- int sock, status;
- SslStateData *sslState = NULL;
-
- debug(26, 3, "sslStart: '%s %s'\n",
- RequestMethodStr[request->method], url);
-
- /* Create socket. */
- sock = comm_open(COMM_NONBLOCKING, 0, 0, url);
- if (sock == COMM_ERROR) {
- debug(26, 4, "sslStart: Failed because we're out of sockets.\n");
- squid_error_url(url,
- request->method,
- ERR_NO_FDS,
- fd_table[fd].ipaddr,
- 500,
- xstrerror());
- return COMM_ERROR;
- }
- sslState = (SslStateData *) xcalloc(1, sizeof(SslStateData));
- sslState->url = xstrdup(url);
- sslState->request = request;
- sslState->mime_hdr = mime_hdr;
- sslState->timeout = getReadTimeout();
- sslState->size_ptr = size_ptr;
- sslState->client.fd = fd;
- sslState->server.fd = sock;
- sslState->server.buf = xmalloc(SSL_BUFSIZ);
- sslState->client.buf = xmalloc(SSL_BUFSIZ);
- comm_set_select_handler(sslState->server.fd,
- COMM_SELECT_CLOSE,
- (PF) sslStateFree,
- (void *) sslState);
-
- /* check if IP is already in cache. It must be.
- * It should be done before this route is called.
- * Otherwise, we cannot check return code for ssl. */
- if (!ipcache_gethostbyname(request->host)) {
- debug(26, 4, "sslstart: Called without IP entry in ipcache. OR lookup failed.\n");
- squid_error_url(url,
+ request_t *request = sslState->request;
+ int status;
+ char *buf = NULL;
+ if (!ipcache_gethostbyname(request->host, 0)) {
+ debug(26, 4, "sslConnect: Unknown host: %s\n", request->host);
+ buf = squid_error_url(sslState->url,
request->method,
ERR_DNS_FAIL,
fd_table[fd].ipaddr,
500,
dns_error_message);
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ comm_write(sslState->client.fd,
+ xstrdup(buf),
+ strlen(buf),
+ 30,
+ sslErrorComplete,
+ (void *) sslState);
return COMM_ERROR;
}
- debug(26, 5, "sslStart: client=%d server=%d\n",
+ debug(26, 5, "sslConnect: client=%d server=%d\n",
sslState->client.fd,
sslState->server.fd);
/* Install lifetime handler */
(PF) sslLifetimeExpire,
(void *) sslState);
/* Open connection. */
- if ((status = comm_connect(sock, request->host, request->port))) {
+ if ((status = comm_connect(fd, request->host, request->port))) {
if (status != EINPROGRESS) {
- squid_error_url(url,
+ buf = squid_error_url(sslState->url,
request->method,
ERR_CONNECT_FAIL,
fd_table[fd].ipaddr,
500,
xstrerror());
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ comm_write(sslState->client.fd,
+ xstrdup(buf),
+ strlen(buf),
+ 30,
+ sslErrorComplete,
+ (void *) sslState);
return COMM_ERROR;
} else {
- debug(26, 5, "sslStart: conn %d EINPROGRESS\n", sock);
+ debug(26, 5, "sslConnect: conn %d EINPROGRESS\n", fd);
/* The connection is in progress, install ssl handler */
comm_set_select_handler(sslState->server.fd,
COMM_SELECT_WRITE,
return COMM_OK;
}
}
- /* We got immediately connected. (can this happen?) */
sslConnected(sslState->server.fd, sslState);
return COMM_OK;
}
+
+int sslStart(fd, url, request, mime_hdr, size_ptr)
+ int fd;
+ char *url;
+ request_t *request;
+ char *mime_hdr;
+ int *size_ptr;
+{
+ /* Create state structure. */
+ SslStateData *sslState = NULL;
+ int sock;
+ char *buf = NULL;
+
+ debug(26, 3, "sslStart: '%s %s'\n",
+ RequestMethodStr[request->method], url);
+
+ /* Create socket. */
+ sock = comm_open(COMM_NONBLOCKING, getTcpOutgoingAddr(), 0, url);
+ if (sock == COMM_ERROR) {
+ debug(26, 4, "sslStart: Failed because we're out of sockets.\n");
+ buf = squid_error_url(url,
+ request->method,
+ ERR_NO_FDS,
+ fd_table[fd].ipaddr,
+ 500,
+ xstrerror());
+ comm_write(sslState->client.fd,
+ xstrdup(buf),
+ strlen(buf),
+ 30,
+ sslErrorComplete,
+ (void *) sslState);
+ return COMM_ERROR;
+ }
+ sslState = xcalloc(1, sizeof(SslStateData));
+ sslState->url = xstrdup(url);
+ sslState->request = requestLink(request);
+ sslState->mime_hdr = mime_hdr;
+ sslState->timeout = getReadTimeout();
+ sslState->size_ptr = size_ptr;
+ sslState->client.fd = fd;
+ sslState->server.fd = sock;
+ sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
+ sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
+ comm_add_close_handler(sslState->server.fd,
+ (PF) sslStateFree,
+ (void *) sslState);
+ comm_add_close_handler(sslState->client.fd,
+ (PF) sslClientClosed,
+ (void *) sslState);
+ ipcache_nbgethostbyname(request->host,
+ sslState->server.fd,
+ (IPH) sslConnect,
+ sslState);
+ return COMM_OK;
+}
-/* $Id: stat.cc,v 1.34 1996/05/15 05:13:25 wessels Exp $ */
+/*
+ * $Id: stat.cc,v 1.35 1996/07/09 03:41:41 wessels Exp $
+ *
+ * DEBUG: section 18 Cache Manager Statistics
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
/*
- * DEBUG: Section 18 stat
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
-#ifdef _SQUID_HPUX_
-#define getrusage(a, b) syscall(SYS_GETRUSAGE, a, b)
-#define getpagesize( ) sysconf(_SC_PAGE_SIZE)
-#endif /* _SQUID_HPUX_ */
-
extern int emulate_httpd_log;
-#define MIN_BUFSIZE (4096)
#define MAX_LINELEN (4096)
#define max(a,b) ((a)>(b)? (a): (b))
Meta_data meta_data;
unsigned long ntcpconn = 0;
unsigned long nudpconn = 0;
+struct _iostats IOStats;
char *stat_describe();
char *mem_describe();
char *elapsed_time();
char *diskFileName();
+/* LOCALS */
+char *open_bracket = "{\n";
+char *close_bracket = "}\n";
+
/* process utilization information */
void stat_utilization_get(obj, sentry)
cacheinfo *obj;
secs = (int) (squid_curtime - squid_starttime);
- storeAppendPrintf(sentry, "{\n");
+ storeAppendPrintf(sentry, open_bracket);
strcpy(p->protoname, "TOTAL");
p->object_count = 0;
/* find the total */
- for (proto_id = 0; proto_id < PROTO_MAX; ++proto_id) {
+ for (proto_id = PROTO_NONE; proto_id < PROTO_MAX; ++proto_id) {
q = &obj->proto_stat_data[proto_id];
p->object_count += q->object_count;
}
/* dump it */
- for (proto_id = 0; proto_id <= PROTO_MAX; ++proto_id) {
+ for (proto_id = PROTO_NONE; proto_id <= PROTO_MAX; ++proto_id) {
p = &obj->proto_stat_data[proto_id];
if (p->hit != 0) {
p->hitratio =
((float) p->hit +
(float) p->miss);
}
- storeAppendPrintf(sentry, "{%s %d %d %d %d %4.2f %d %d %d}\n",
+ storeAppendPrintf(sentry, "{%8.8s %d %d %d %d %4.2f %d %d %d}\n",
p->protoname,
p->object_count,
p->kb.max,
p->transferbyte);
}
- storeAppendPrintf(sentry, "}\n");
+ storeAppendPrintf(sentry, close_bracket);
+}
+
+void stat_io_get(sentry)
+ StoreEntry *sentry;
+{
+ int i;
+
+ storeAppendPrintf(sentry, open_bracket);
+ storeAppendPrintf(sentry, "{HTTP I/O}\n");
+ storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Http.reads);
+ storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n",
+ IOStats.Http.reads_deferred,
+ percent(IOStats.Http.reads_deferred, IOStats.Http.reads));
+ storeAppendPrintf(sentry, "{Read Histogram:}\n");
+ for (i = 0; i < 16; i++) {
+ storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n",
+ i ? (1 << (i - 1)) + 1 : 1,
+ 1 << i,
+ IOStats.Http.read_hist[i],
+ percent(IOStats.Http.read_hist[i], IOStats.Http.reads));
+ }
+
+ storeAppendPrintf(sentry, "{}\n");
+ storeAppendPrintf(sentry, "{FTP I/O}\n");
+ storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Ftp.reads);
+ storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n",
+ IOStats.Ftp.reads_deferred,
+ percent(IOStats.Ftp.reads_deferred, IOStats.Ftp.reads));
+ storeAppendPrintf(sentry, "{Read Histogram:}\n");
+ for (i = 0; i < 16; i++) {
+ storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n",
+ i ? (1 << (i - 1)) + 1 : 1,
+ 1 << i,
+ IOStats.Ftp.read_hist[i],
+ percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads));
+ }
+
+ storeAppendPrintf(sentry, close_bracket);
}
int size = 0;
protocol_t proto_id;
/* sum all size, exclude total */
- for (proto_id = 0; proto_id < PROTO_MAX; proto_id++)
+ for (proto_id = PROTO_NONE; proto_id < PROTO_MAX; proto_id++)
size += obj->proto_stat_data[proto_id].kb.now;
return size;
}
-/* process general IP cache information */
-void stat_general_get(obj, sentry)
- cacheinfo *obj;
- StoreEntry *sentry;
-{
- /* have to use old method for this guy,
- * otherwise we have to make ipcache know about StoreEntry */
- stat_ipcache_get(sentry, obj);
-}
-
-
/* process objects list */
void stat_objects_get(obj, sentry, vm_or_not)
cacheinfo *obj;
int N = 0;
int obj_size;
- storeAppendPrintf(sentry, "{\n");
+ storeAppendPrintf(sentry, open_bracket);
for (entry = storeGetFirst();
entry != NULL;
mem_describe(entry),
stat_describe(entry));
}
- storeAppendPrintf(sentry, "}\n");
+ storeAppendPrintf(sentry, close_bracket);
}
StoreEntry *sentry;
{
- if (strncmp(req, "objects", strlen("objects")) == 0) {
+ if (strcmp(req, "objects") == 0) {
stat_objects_get(obj, sentry, 0);
- } else if (strncmp(req, "vm_objects", strlen("vm_objects")) == 0) {
+ } else if (strcmp(req, "vm_objects") == 0) {
stat_objects_get(obj, sentry, 1);
- } else if (strncmp(req, "general", strlen("general")) == 0) {
- stat_general_get(obj, sentry);
- } else if (strncmp(req, "utilization", strlen("utilization")) == 0) {
+ } else if (strcmp(req, "general") == 0) {
+ stat_ipcache_get(sentry);
+ } else if (strcmp(req, "general") == 0) {
+ stat_ipcache_get(sentry);
+ } else if (strcmp(req, "utilization") == 0) {
stat_utilization_get(obj, sentry);
+ } else if (strcmp(req, "io") == 0) {
+ stat_io_get(sentry);
+ } else if (strcmp(req, "reply_headers") == 0) {
+ httpReplyHeaderStats(sentry);
}
}
int errflag_unused;
log_read_data_t *data;
{
- storeAppendPrintf(data->sentry, "}\n");
+ storeAppendPrintf(data->sentry, close_bracket);
storeComplete(data->sentry);
safe_free(data);
}
storeComplete(sentry);
return;
}
- data = (log_read_data_t *) xmalloc(sizeof(log_read_data_t));
- memset(data, '\0', sizeof(log_read_data_t));
+ data = xcalloc(1, sizeof(log_read_data_t));
data->sentry = sentry;
storeAppendPrintf(sentry, "{\n");
file_walk(obj->logfile_fd, (FILE_WALK_HD) logReadEndHandler,
int size_unused;
squid_read_data_t *data;
{
- static char tempbuf[MAX_LINELEN];
- tempbuf[0] = '\0';
storeAppendPrintf(data->sentry, "{\"%s\"}\n", buf);
return 0;
}
int errflag_unused;
squid_read_data_t *data;
{
- storeAppendPrintf(data->sentry, "}\n");
+ storeAppendPrintf(data->sentry, close_bracket);
storeComplete(data->sentry);
file_close(data->fd);
safe_free(data);
{
squid_read_data_t *data;
- data = (squid_read_data_t *) xmalloc(sizeof(squid_read_data_t));
- memset(data, '\0', sizeof(squid_read_data_t));
+ data = xcalloc(1, sizeof(squid_read_data_t));
data->sentry = sentry;
data->fd = file_open((char *) ConfigFile, NULL, O_RDONLY);
- storeAppendPrintf(sentry, "{\n");
+ storeAppendPrintf(sentry, open_bracket);
file_walk(data->fd, (FILE_WALK_HD) squidReadEndHandler, (void *) data,
(FILE_WALK_LHD) squidReadHandler, (void *) data);
}
{
edge *e = NULL;
dom_list *d = NULL;
+ icp_opcode op;
- storeAppendPrintf(sentry, "{\n");
+ storeAppendPrintf(sentry, open_bracket);
- if (getFirstEdge() == (edge *) NULL) {
+ if (getFirstEdge() == NULL)
storeAppendPrintf(sentry, "{There are no neighbors installed.}\n");
- }
for (e = getFirstEdge(); e; e = getNextEdge(e)) {
if (e->host == NULL)
fatal_dump("Found an edge without a hostname!");
- storeAppendPrintf(sentry, "\n{Hostname: %s}\n", e->host);
- storeAppendPrintf(sentry, "{Edge type: %s}\n",
- e->type == EDGE_PARENT ? "parent" : "neighbor");
- storeAppendPrintf(sentry, "{Status: %s}\n",
+ storeAppendPrintf(sentry, "\n{%-11.11s: %s/%d/%d}\n",
+ e->type == EDGE_PARENT ? "Parent" : "Sibling",
+ e->host,
+ e->http_port,
+ e->icp_port);
+ storeAppendPrintf(sentry, "{Status : %s}\n",
e->neighbor_up ? "Up" : "Down");
- storeAppendPrintf(sentry, "{UDP PORT: %d}\n", e->udp_port);
- storeAppendPrintf(sentry, "{ASCII PORT: %d}\n", e->ascii_port);
- storeAppendPrintf(sentry, "{ACK DEFICIT: %d}\n", e->ack_deficit);
- storeAppendPrintf(sentry, "{PINGS SENT: %d}\n", e->num_pings);
- storeAppendPrintf(sentry, "{PINGS ACKED: %d}\n", e->pings_acked);
+ storeAppendPrintf(sentry, "{AVG RTT : %d msec}\n", e->stats.rtt);
+ storeAppendPrintf(sentry, "{ACK DEFICIT: %8d}\n", e->stats.ack_deficit);
+ storeAppendPrintf(sentry, "{PINGS SENT : %8d}\n", e->stats.pings_sent);
+ storeAppendPrintf(sentry, "{PINGS ACKED: %8d %3d%%}\n",
+ e->stats.pings_acked,
+ percent(e->stats.pings_acked, e->stats.pings_sent));
+ storeAppendPrintf(sentry, "{Histogram of PINGS ACKED:}\n");
+ for (op = ICP_OP_INVALID; op < ICP_OP_END; op++) {
+ if (e->stats.counts[op] == 0)
+ continue;
+ storeAppendPrintf(sentry, "{%-10.10s : %8d %3d%%}\n",
+ IcpOpcodeStr[op],
+ e->stats.counts[op],
+ percent(e->stats.counts[op], e->stats.pings_acked));
+ }
+ storeAppendPrintf(sentry, "{FETCHES : %8d %3d%%}\n",
+ e->stats.fetches,
+ percent(e->stats.fetches, e->stats.pings_acked));
+
if (e->last_fail_time) {
storeAppendPrintf(sentry, "{Last failed connect() at: %s}\n",
mkhttpdlogtime(&(e->last_fail_time)));
else
storeAppendPrintf(sentry, "!%s ", d->domain);
}
- storeAppendPrintf(sentry, "}\n");
+ storeAppendPrintf(sentry, close_bracket); /* } */
}
- storeAppendPrintf(sentry, "}\n");
+ storeAppendPrintf(sentry, close_bracket);
}
+#if XMALLOC_STATISTICS
+void info_get_mallstat(size, number, sentry)
+ int size, number;
+ StoreEntry *sentry;
+{
+ static char line[MAX_LINELEN];
+ if (number > 0)
+ storeAppendPrintf(sentry, "{\t%d = %d}\n", size, number);
+}
+#endif
void info_get(obj, sentry)
char *tod = NULL;
static char line[MAX_LINELEN];
wordlist *p = NULL;
+#ifdef HAVE_MALLINFO
+ int t;
+#endif
#if defined(HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
struct rusage rusage;
memset(line, '\0', SM_PAGE_SIZE);
- storeAppendPrintf(sentry, "{\n");
-
+ storeAppendPrintf(sentry, open_bracket);
storeAppendPrintf(sentry, "{Squid Object Cache: Version %s}\n", version_string);
-
tod = mkrfc850(&squid_starttime);
-
storeAppendPrintf(sentry, "{Start Time:\t%s}\n", tod);
-
tod = mkrfc850(&squid_curtime);
storeAppendPrintf(sentry, "{Current Time:\t%s}\n", tod);
/* -------------------------------------------------- */
- storeAppendPrintf(sentry, "{Connection information for %s:}\n",
- appname);
- storeAppendPrintf(sentry, "{\tNumber of TCP connections:\t%lu}\n",
- ntcpconn);
- storeAppendPrintf(sentry, "{\tNumber of UDP connections:\t%lu}\n",
- nudpconn);
+ storeAppendPrintf(sentry, "{Connection information for %s:}\n", appname);
+
+ storeAppendPrintf(sentry, "{\tNumber of TCP connections:\t%lu}\n", ntcpconn);
+
+ storeAppendPrintf(sentry, "{\tNumber of UDP connections:\t%lu}\n", nudpconn);
{
float f;
f = squid_curtime - squid_starttime;
- storeAppendPrintf(sentry, "{\tConnections per hour:\t%.1f}\n",
- f == 0.0 ? 0.0 :
+ storeAppendPrintf(sentry, "{\tConnections per hour:\t%.1f}\n", f == 0.0 ? 0.0 :
((ntcpconn + nudpconn) / (f / 3600)));
}
/* -------------------------------------------------- */
- storeAppendPrintf(sentry, "{Cache information for %s:}\n", appname);
-
- storeAppendPrintf(sentry, "{\tStorage Swap size:\t%d MB}\n", storeGetSwapSize() >> 10);
-
- storeAppendPrintf(sentry, "{\tStorage Mem size:\t%d KB}\n", storeGetMemSize() >> 10);
+ storeAppendPrintf(sentry, "{Cache information for %s:}\n",
+ appname);
+ storeAppendPrintf(sentry, "{\tStorage Swap size:\t%d MB}\n",
+ storeGetSwapSize() >> 10);
+ storeAppendPrintf(sentry, "{\tStorage Mem size:\t%d KB}\n",
+ storeGetMemSize() >> 10);
tod = mkrfc850(&next_cleaning);
storeAppendPrintf(sentry, "{\tStorage Expiration at:\t%s}\n", tod);
-#if defined(HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
+#if HAVE_GETRUSAGE && defined(RUSAGE_SELF)
storeAppendPrintf(sentry, "{Resource usage for %s:}\n", appname);
-
getrusage(RUSAGE_SELF, &rusage);
- storeAppendPrintf(sentry, "{\tCPU Usage: user %d sys %d}\n{\tProcess Size: rss %d KB}\n",
- rusage.ru_utime.tv_sec, rusage.ru_stime.tv_sec,
+ storeAppendPrintf(sentry, "{\tCPU Usage: user %d sys %d}\n",
+ (int) rusage.ru_utime.tv_sec, (int) rusage.ru_stime.tv_sec);
+ storeAppendPrintf(sentry, "{\tProcess Size: rss %ld KB}\n",
rusage.ru_maxrss * getpagesize() >> 10);
- storeAppendPrintf(sentry, "{\tPage faults with physical i/o:\t%d}\n",
+ storeAppendPrintf(sentry, "{\tPage faults with physical i/o: %ld}\n",
rusage.ru_majflt);
#endif
#if HAVE_MALLINFO
mp = mallinfo();
-
- storeAppendPrintf(sentry, "{Memory usage for %s via mallinfo():}\n", appname);
-
- storeAppendPrintf(sentry, "{\ttotal space in arena:\t%d KB}\n", mp.arena >> 10);
- storeAppendPrintf(sentry, "{\tnumber of ordinary blocks:\t%d}\n", mp.ordblks);
- storeAppendPrintf(sentry, "{\tnumber of small blocks:\t%d}\n", mp.smblks);
- if (mp.hblks) {
- storeAppendPrintf(sentry, "{\tnumber of holding blocks:\t%d}\n", mp.hblks);
- }
- if (mp.hblkhd) {
- storeAppendPrintf(sentry, "{\tspace in holding block headers:\t%d}\n", mp.hblkhd);
- }
- if (mp.usmblks) {
- storeAppendPrintf(sentry, "{\tspace in small blocks in use:\t%d}\n", mp.usmblks);
- }
- if (mp.fsmblks) {
- storeAppendPrintf(sentry, "{\tspace in free blocks:\t%d}\n", mp.fsmblks);
- }
- storeAppendPrintf(sentry, "{\tspace in ordinary blocks in use:\t%d KB}\n",
- mp.uordblks >> 10);
- storeAppendPrintf(sentry, "{\tspace in free ordinary blocks:\t%d KB}\n", mp.fordblks >> 10);
- if (mp.keepcost) {
- storeAppendPrintf(sentry, "{\tcost of enabling keep option:\t%d}\n", mp.keepcost);
- }
+ storeAppendPrintf(sentry, "{Memory usage for %s via mallinfo():}\n", appname
+);
+ storeAppendPrintf(sentry, "{\tTotal space in arena: %6d KB}\n",
+ mp.arena >> 10);
+ storeAppendPrintf(sentry, "{\tOrdinary blocks: %6d KB %6d blks}\n",
+ mp.uordblks >> 10, mp.ordblks);
+ storeAppendPrintf(sentry, "{\tSmall blocks: %6d KB %6d blks}\n",
+ mp.usmblks >> 10, mp.smblks);
+ storeAppendPrintf(sentry, "{\tHolding blocks: %6d KB %6d blks}\n",
+ mp.hblkhd >> 10, mp.hblks);
+ storeAppendPrintf(sentry, "{\tFree Small blocks: %6d KB}\n",
+ mp.fsmblks >> 10);
+ storeAppendPrintf(sentry, "{\tFree Ordinary blocks: %6d KB}\n",
+ mp.fordblks >> 10);
+ t = mp.uordblks + mp.usmblks + mp.hblkhd;
+ storeAppendPrintf(sentry, "{\tTotal in use: %6d KB %d%%}\n",
+ t >> 10, percent(t, mp.arena));
+ t = mp.fsmblks + mp.fordblks;
+ storeAppendPrintf(sentry, "{\tTotal free: %6d KB %d%%}\n",
+ t >> 10, percent(t, mp.arena));
+#ifdef WE_DONT_USE_KEEP
+ storeAppendPrintf(sentry, "{\tKeep option: %6d KB}\n",
+ mp.keepcost >> 10);
+#endif
#if HAVE_EXT_MALLINFO
storeAppendPrintf(sentry, "{\tmax size of small blocks:\t%d}\n", mp.mxfast);
storeAppendPrintf(sentry, "{\tnumber of small blocks in a holding block:\t%d}\n",
mp.allocated);
storeAppendPrintf(sentry, "{\tbytes used in maintaining the free tree:\t%d}\n",
mp.treeoverhead);
-
#endif /* HAVE_EXT_MALLINFO */
-
#endif /* HAVE_MALLINFO */
storeAppendPrintf(sentry, "{File descriptor usage for %s:}\n", appname);
-
- storeAppendPrintf(sentry, "{\tMax number of file desc available:\t%d}\n", getMaxFD());
-
- storeAppendPrintf(sentry, "{\tLargest file desc currently in use:\t%d}\n",
+ storeAppendPrintf(sentry, "{\tMax number of file desc available: %4d}\n",
+ FD_SETSIZE);
+ storeAppendPrintf(sentry, "{\tLargest file desc currently in use: %4d}\n",
fdstat_biggest_fd());
-
- storeAppendPrintf(sentry, "{\tAvailable number of file descriptors :\t%d}\n",
+ storeAppendPrintf(sentry, "{\tAvailable number of file descriptors: %4d}\n",
fdstat_are_n_free_fd(0));
-
- storeAppendPrintf(sentry, "{\tReserved number of file descriptors :\t%d}\n",
+ storeAppendPrintf(sentry, "{\tReserved number of file descriptors: %4d}\n",
RESERVED_FD);
{
- int i, max_fd = getMaxFD();
+ int i;
char *s = NULL;
storeAppendPrintf(sentry, "{\tActive file descriptors:}\n");
- for (i = 0; i < max_fd; i++) {
+ for (i = 0; i < FD_SETSIZE; i++) {
int lft, to;
if (!fdstat_isopen(i))
continue;
line[0] = '\0';
switch (fdstat_type(i)) {
- case Socket:
+ case FD_SOCKET:
/* the lifetime should be greater than curtime */
lft = comm_get_fd_lifetime(i);
to = comm_get_fd_timeout(i);
(int) max((to - squid_curtime), 0),
fd_note(i, NULL));
break;
- case File:
+ case FD_FILE:
storeAppendPrintf(sentry, "{\t\t(%3d = FILE) %s}\n", i,
(s = diskFileName(i)) ? s : "Unknown");
break;
- case Pipe:
+ case FD_PIPE:
storeAppendPrintf(sentry, "{\t\t(%3d = PIPE) %s}\n", i, fd_note(i, NULL));
break;
- case LOG:
+ case FD_LOG:
storeAppendPrintf(sentry, "{\t\t(%3d = LOG) %s}\n", i, fd_note(i, NULL));
break;
- case Unknown:
+ case FD_UNKNOWN:
default:
storeAppendPrintf(sentry, "{\t\t(%3d = UNKNOWN) %s}\n", i, fd_note(i, NULL));
break;
}
}
storeAppendPrintf(sentry, "{Internal Data Structures:}\n");
+ storeAppendPrintf(sentry, "{\tHot Object Cache Items %d}\n",
+ meta_data.hot_vm);
+ storeAppendPrintf(sentry, "{\tStoreEntries with MemObjects %d}\n",
+ meta_data.store_in_mem_objects);
+
storeAppendPrintf(sentry, "{Meta Data:}\n");
- storeAppendPrintf(sentry, "{\t\tStoreEntry %d x %d bytes = %d KB}\n",
+ storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
+ "StoreEntry",
meta_data.store_entries,
(int) sizeof(StoreEntry),
(int) (meta_data.store_entries * sizeof(StoreEntry) >> 10));
- storeAppendPrintf(sentry, "{\t\tStoreMemObject %d x %d bytes = %d KB}\n",
- meta_data.store_in_mem_objects,
- (int) sizeof(MemObject),
- (int) (meta_data.store_in_mem_objects * sizeof(MemObject) >> 10));
-
- storeAppendPrintf(sentry, "{\t\tIPCacheEntry %d x %d bytes = %d KB}\n",
+ storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
+ "IPCacheEntry",
meta_data.ipcache_count,
(int) sizeof(ipcache_entry),
(int) (meta_data.ipcache_count * sizeof(ipcache_entry) >> 10));
- storeAppendPrintf(sentry, "{\t\tHash link %d x %d bytes = %d KB}\n",
+ storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
+ "Hash link",
meta_data.hash_links = hash_links_allocated,
(int) sizeof(hash_link),
(int) (meta_data.hash_links * sizeof(hash_link) >> 10));
- storeAppendPrintf(sentry, "{\t\tURL strings %d KB}\n",
+ storeAppendPrintf(sentry, "{\t%-25.25s = %6d KB}\n",
+ "URL strings",
meta_data.url_strings >> 10);
- storeAppendPrintf(sentry, "{\t\tHot Object Cache Items %d}\n", meta_data.hot_vm);
+ storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n",
+ "Pool MemObject structures",
+ mem_obj_pool.total_pages_allocated,
+ mem_obj_pool.page_size,
+ mem_obj_pool.total_pages_allocated * mem_obj_pool.page_size >> 10,
+ (mem_obj_pool.total_pages_allocated - mem_obj_pool.n_pages_in_use) * mem_obj_pool.page_size >> 10);
+
+ storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n",
+ "Pool for Request structures",
+ request_pool.total_pages_allocated,
+ request_pool.page_size,
+ request_pool.total_pages_allocated * request_pool.page_size >> 10,
+ (request_pool.total_pages_allocated - request_pool.n_pages_in_use) * request_pool.page_size >> 10);
+
+ storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n",
+ "Pool for in-memory object data",
+ sm_stats.total_pages_allocated,
+ sm_stats.page_size,
+ sm_stats.total_pages_allocated * sm_stats.page_size >> 10,
+ (sm_stats.total_pages_allocated - sm_stats.n_pages_in_use) * sm_stats.page_size >> 10);
- storeAppendPrintf(sentry, "{\t\tPool for disk I/O %d KB (Free %d KB)}\n",
+ storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n",
+ "Pool for disk I/O",
+ disk_stats.total_pages_allocated,
+ disk_stats.page_size,
disk_stats.total_pages_allocated * disk_stats.page_size >> 10,
(disk_stats.total_pages_allocated - disk_stats.n_pages_in_use) * disk_stats.page_size >> 10);
- storeAppendPrintf(sentry, "{\t\tPool for in-memory objects %d KB (Free %d KB)}\n",
- sm_stats.total_pages_allocated * sm_stats.page_size >> 10,
- (sm_stats.total_pages_allocated - sm_stats.n_pages_in_use) * sm_stats.page_size >> 10);
+ storeAppendPrintf(sentry, "{\t%-25.25s = %6d KB}\n",
+ "Miscellaneous",
+ meta_data.misc >> 10);
- storeAppendPrintf(sentry, "{\tTotal Accounted %d KB}\n",
+ storeAppendPrintf(sentry, "{\t%-25.25s = %6d KB}\n",
+ "Total Accounted",
(int) (meta_data.store_entries * sizeof(StoreEntry) +
- meta_data.store_in_mem_objects * sizeof(MemObject) +
meta_data.ipcache_count * sizeof(ipcache_entry) +
meta_data.hash_links * sizeof(hash_link) +
sm_stats.total_pages_allocated * sm_stats.page_size +
disk_stats.total_pages_allocated * disk_stats.page_size +
- meta_data.url_strings) >> 10);
+ request_pool.total_pages_allocated * request_pool.page_size +
+ mem_obj_pool.total_pages_allocated * mem_obj_pool.page_size +
+ meta_data.url_strings +
+ meta_data.misc) >> 10);
+
+#if XMALLOC_STATISTICS
+ storeAppendPrintf(sentry, "{Memory allocation statistics}\n");
+ malloc_statistics(info_get_mallstat, sentry);
+#endif
- storeAppendPrintf(sentry, "}\n");
+ storeAppendPrintf(sentry, close_bracket);
}
memset(line, '\0', MAX_LINELEN);
- storeAppendPrintf(sentry, "{\n");
+ storeAppendPrintf(sentry, open_bracket);
storeAppendPrintf(sentry, "{VM-Max %d \"# Maximum hot-vm cache (MB)\"}\n",
getCacheMemMax() / (1 << 20));
storeAppendPrintf(sentry, "{ReadTimeout %d \"# Maximum idle connection (s)\"}\n", getReadTimeout());
- storeAppendPrintf(sentry, "{ClientLifetime %d \"# Lifetime for incoming ascii port requests or outgoing clients (s)\"}\n", getClientLifetime());
+ storeAppendPrintf(sentry, "{ClientLifetime %d \"# Lifetime for incoming HTTP requests or outgoing clients (s)\"}\n", getClientLifetime());
storeAppendPrintf(sentry, "{CleanRate %d \"# Rate for periodic object expiring\"}\n",
getCleanRate());
httpd_accel_mode);
/* end of stats */
- storeAppendPrintf(sentry, "}\n");
+ storeAppendPrintf(sentry, close_bracket);
}
-void log_append(obj, url, id, size, action, method, http_code, msec, ident)
+void log_append(obj, url, id, size, action, method, http_code, msec, ident, hier)
cacheinfo *obj;
char *url;
char *id;
int http_code;
int msec;
char *ident;
+ hier_code hier;
{
static char tmp[6000]; /* MAX_URL is 4096 */
char *buf = NULL;
action,
size);
else
- sprintf(tmp, "%9d.%03d %6d %s %s/%03d %d %s %s %s\n",
+ sprintf(tmp, "%9d.%03d %6d %s %s/%03d/%s %d %s %s %s\n",
(int) current_time.tv_sec,
(int) current_time.tv_usec / 1000,
msec,
id,
action,
http_code,
+ hier_strings[hier],
size,
method,
url,
ident);
-
-
if (file_write(obj->logfile_fd, buf = xstrdup(tmp), strlen(tmp),
obj->logfile_access, NULL, NULL) != DISK_OK) {
debug(18, 1, "log_append: File write failed.\n");
cacheinfo *obj;
StoreEntry *sentry;
{
- static char tempbuf[MAX_LINELEN];
-
if (obj->logfile_status == LOG_DISABLE) {
obj->logfile_status = LOG_ENABLE;
}
/* at the moment, store one char to make a storage manager happy */
storeAppendPrintf(sentry, " ");
- storeAppend(sentry, tempbuf, strlen(tempbuf));
}
void log_disable(obj, sentry)
cacheinfo *obj;
StoreEntry *sentry;
{
- static char tempbuf[MAX_LINELEN];
-
-
- /* what should be done here. Erase file ??? or move it to another name */
- /* At the moment, just erase it. */
- /* bug here need to be fixed. what if there are still data in memory. Need flush here */
+ /* what should be done here. Erase file ??? or move it to another name? At the moment, just erase it. bug here need to be fixed. what if there are still data in memory. Need flush here */
if (obj->logfile_status == LOG_ENABLE)
file_close(obj->logfile_fd);
}
/* at the moment, store one char to make a storage manager happy */
storeAppendPrintf(sentry, " ");
- storeAppend(sentry, tempbuf, strlen(tempbuf));
}
cacheinfo *obj = NULL;
int i;
- obj = (cacheinfo *) xmalloc(sizeof(cacheinfo));
- memset(obj, '\0', sizeof(cacheinfo));
-
+ obj = xcalloc(1, sizeof(cacheinfo));
obj->stat_get = stat_get;
obj->info_get = info_get;
obj->cache_size_get = cache_size_get;
-
obj->log_get_start = log_get_start;
obj->log_status_get = log_status_get;
obj->log_append = log_append;
obj->log_enable = log_enable;
obj->log_disable = log_disable;
obj->logfile_status = LOG_ENABLE;
-
obj->squid_get_start = squid_get_start;
-
obj->parameter_get = parameter_get;
obj->server_list = server_list;
- memcpy(obj->logfilename, logfilename, (int) (strlen(logfilename) + 1) % 256);
+ xmemcpy(obj->logfilename, logfilename, (int) (strlen(logfilename) + 1) % 256);
obj->logfile_fd = file_open(obj->logfilename, NULL, O_RDWR | O_CREAT);
if (obj->logfile_fd == DISK_ERROR) {
debug(18, 0, "%s: %s\n", obj->logfilename, xstrerror());
obj->proto_miss = proto_miss;
obj->NotImplement = dummyhandler;
- for (i = 0; i <= PROTO_MAX; i++) {
+ for (i = PROTO_NONE; i <= PROTO_MAX; i++) {
switch (i) {
case PROTO_HTTP:
strcpy(obj->proto_stat_data[i].protoname, "HTTP");
strncat(state, "/", sizeof(state));
switch (entry->ping_status) {
- case WAITING:
+ case PING_WAITING:
strncat(state, "PING-WAIT", sizeof(state));
break;
- case TIMEOUT:
+ case PING_TIMEOUT:
strncat(state, "PING-TIMEOUT", sizeof(state));
break;
- case DONE:
+ case PING_DONE:
strncat(state, "PING-DONE", sizeof(state));
break;
- case NOPING:
+ case PING_NONE:
strncat(state, "NO-PING", sizeof(state));
break;
default:
- strncat(state, "YEEHAH", sizeof(state));
+ strncat(state, "HELP!!", sizeof(state));
break;
}
return (state);
file_close(CacheInfo->logfile_fd);
CacheInfo->logfile_fd = file_open(fname, NULL, O_RDWR | O_CREAT | O_APPEND);
if (CacheInfo->logfile_fd == DISK_ERROR) {
- debug(18, 0, "rotate_logs: Cannot open logfile: %s\n", fname);
+ debug(18, 0, "stat_rotate_log: Cannot open logfile: %s\n", fname);
CacheInfo->logfile_status = LOG_DISABLE;
fatal("Cannot open logfile.");
}
-/* $Id: stmem.cc,v 1.9 1996/04/12 21:41:40 wessels Exp $ */
+/*
+ * $Id: stmem.cc,v 1.10 1996/07/09 03:41:42 wessels Exp $
+ *
+ * DEBUG: section 19 Memory Primitives
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
-/*
- * DEBUG: Section 19 stmem:
+/*
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
stmem_stats sm_stats;
stmem_stats disk_stats;
+stmem_stats request_pool;
+stmem_stats mem_obj_pool;
#define min(x,y) ((x)<(y)? (x) : (y))
if (mem->head && mem->tail && (mem->tail->len < SM_PAGE_SIZE)) {
avail_len = SM_PAGE_SIZE - (mem->tail->len);
len_to_copy = min(avail_len, len);
- memcpy((mem->tail->data + mem->tail->len), data, len_to_copy);
+ xmemcpy((mem->tail->data + mem->tail->len), data, len_to_copy);
/* Adjust the ptr and len according to what was deposited in the page */
data += len_to_copy;
len -= len_to_copy;
}
while (len > 0) {
len_to_copy = min(len, SM_PAGE_SIZE);
- p = (mem_node) xcalloc(1, sizeof(Mem_Node));
+ p = xcalloc(1, sizeof(Mem_Node));
p->next = NULL;
p->len = len_to_copy;
p->data = get_free_4k_page();
- memcpy(p->data, data, len_to_copy);
+ xmemcpy(p->data, data, len_to_copy);
if (!mem->head) {
/* The chain is empty */
mem_node p = mem->head;
int t_off = mem->origin_offset;
int bytes_to_go = size;
- char *ptr_to_buf;
+ char *ptr_to_buf = NULL;
int bytes_from_this_packet = 0;
int bytes_into_this_packet = 0;
debug(19, 6, "memCopy: offset %d: size %d\n", offset, size);
+ if (p == NULL)
+ fatal_dump("memCopy: NULL mem_node");
+
if (size <= 0)
return size;
bytes_from_this_packet = min(bytes_to_go,
p->len - bytes_into_this_packet);
- memcpy(buf, p->data + bytes_into_this_packet, bytes_from_this_packet);
+ xmemcpy(buf, p->data + bytes_into_this_packet, bytes_from_this_packet);
bytes_to_go -= bytes_from_this_packet;
ptr_to_buf = buf + bytes_from_this_packet;
p = p->next;
while (p && bytes_to_go > 0) {
if (bytes_to_go > p->len) {
- memcpy(ptr_to_buf, p->data, p->len);
+ xmemcpy(ptr_to_buf, p->data, p->len);
ptr_to_buf += p->len;
bytes_to_go -= p->len;
} else {
- memcpy(ptr_to_buf, p->data, bytes_to_go);
+ xmemcpy(ptr_to_buf, p->data, bytes_to_go);
bytes_to_go -= bytes_to_go;
}
p = p->next;
/* Do whatever is necessary to begin storage of new object */
mem_ptr memInit()
{
- mem_ptr new = (mem_ptr) xcalloc(1, sizeof(Mem_Hdr));
-
+ mem_ptr new = xcalloc(1, sizeof(Mem_Hdr));
new->tail = new->head = NULL;
-
new->mem_free = memFree;
new->mem_free_data = memFreeData;
new->mem_free_data_upto = memFreeDataUpto;
new->mem_append = memAppend;
new->mem_copy = memCopy;
new->mem_grep = memGrep;
-
return new;
}
+void *get_free_request_t()
+{
+ void *req = NULL;
+ if (!empty_stack(&request_pool.free_page_stack)) {
+ req = pop(&request_pool.free_page_stack);
+ } else {
+ req = xmalloc(sizeof(request_t));
+ request_pool.total_pages_allocated++;
+ }
+ request_pool.n_pages_in_use++;
+ if (req == NULL)
+ fatal_dump("get_free_request_t: Null pointer?");
+ memset(req, '\0', sizeof(request_t));
+ return (req);
+}
+
+void put_free_request_t(req)
+ void *req;
+{
+ if (full_stack(&request_pool.free_page_stack))
+ request_pool.total_pages_allocated--;
+ request_pool.n_pages_in_use--;
+ push(&request_pool.free_page_stack, req);
+}
+
+void *get_free_mem_obj()
+{
+ void *mem = NULL;
+ if (!empty_stack(&mem_obj_pool.free_page_stack)) {
+ mem = pop(&mem_obj_pool.free_page_stack);
+ } else {
+ mem = xmalloc(sizeof(MemObject));
+ mem_obj_pool.total_pages_allocated++;
+ }
+ mem_obj_pool.n_pages_in_use++;
+ if (mem == NULL)
+ fatal_dump("get_free_mem_obj: Null pointer?");
+ memset(mem, '\0', sizeof(MemObject));
+ return (mem);
+}
+
+void put_free_mem_obj(mem)
+ void *mem;
+{
+ if (full_stack(&mem_obj_pool.free_page_stack))
+ mem_obj_pool.total_pages_allocated--;
+ mem_obj_pool.n_pages_in_use--;
+ push(&mem_obj_pool.free_page_stack, mem);
+}
+
/* PBD 12/95: Memory allocator routines for saving and reallocating fixed
* size blocks rather than mallocing and freeing them */
char *get_free_4k_page()
{
char *page = NULL;
-
if (!empty_stack(&sm_stats.free_page_stack)) {
page = pop(&sm_stats.free_page_stack);
} else {
#if USE_MEMALIGN
- page = (char *) memalign(SM_PAGE_SIZE, SM_PAGE_SIZE);
+ page = memalign(SM_PAGE_SIZE, SM_PAGE_SIZE);
if (!page)
fatal_dump(NULL);
#else
- page = (char *) xmalloc(SM_PAGE_SIZE);
+ page = xmalloc(SM_PAGE_SIZE);
#endif
sm_stats.total_pages_allocated++;
}
void put_free_4k_page(page)
char *page;
{
- static stack_overflow_warning_toggle;
-
#if USE_MEMALIGN
if ((int) page % SM_PAGE_SIZE)
fatal_dump("Someone tossed a string into the 4k page pool");
#endif
- if (full_stack(&sm_stats.free_page_stack)) {
+ if (full_stack(&sm_stats.free_page_stack))
sm_stats.total_pages_allocated--;
- if (!stack_overflow_warning_toggle) {
- debug(19, 0, "Stack of free stmem pages overflowed. Resize it?");
- stack_overflow_warning_toggle++;
- }
- }
sm_stats.n_pages_in_use--;
- /* Call push regardless if it's full, cause it's just going to release the
- * page if stack is full */
push(&sm_stats.free_page_stack, page);
}
char *get_free_8k_page()
{
char *page = NULL;
-
if (!empty_stack(&disk_stats.free_page_stack)) {
page = pop(&disk_stats.free_page_stack);
} else {
#if USE_MEMALIGN
- page = (char *) memalign(DISK_PAGE_SIZE, DISK_PAGE_SIZE);
+ page = memalign(DISK_PAGE_SIZE, DISK_PAGE_SIZE);
if (!page)
fatal_dump(NULL);
#else
- page = (char *) xmalloc(DISK_PAGE_SIZE);
+ page = xmalloc(DISK_PAGE_SIZE);
#endif
disk_stats.total_pages_allocated++;
}
void put_free_8k_page(page)
char *page;
{
- static stack_overflow_warning_toggle;
-
#if USE_MEMALIGN
if ((int) page % DISK_PAGE_SIZE)
fatal_dump("Someone tossed a string into the 8k page pool");
#endif
-
- if (full_stack(&disk_stats.free_page_stack)) {
+ if (full_stack(&disk_stats.free_page_stack))
disk_stats.total_pages_allocated--;
- if (!stack_overflow_warning_toggle) {
- debug(19, 0, "Stack of free disk pages overflowed. Resize it?");
- stack_overflow_warning_toggle++;
- }
- }
disk_stats.n_pages_in_use--;
- /* Call push regardless if it's full, cause it's just going to release the
- * page if stack is full */
push(&disk_stats.free_page_stack, page);
}
disk_stats.n_pages_free = 0;
disk_stats.n_pages_in_use = 0;
+ request_pool.page_size = sizeof(request_t);
+ request_pool.total_pages_allocated = 0;
+ request_pool.n_pages_free = 0;
+ request_pool.n_pages_in_use = 0;
+
+ mem_obj_pool.page_size = sizeof(MemObject);
+ mem_obj_pool.total_pages_allocated = 0;
+ mem_obj_pool.n_pages_free = 0;
+ mem_obj_pool.n_pages_in_use = 0;
+
/* use -DPURIFY=1 on the compile line to enable Purify checks */
#if !PURIFY
- /* 4096 * 10000 pages = 40MB + CacheMemMax in pages */
- init_stack(&sm_stats.free_page_stack, 10000 + (getCacheMemMax() / SM_PAGE_SIZE));
- /* 8096 * 1000 pages = 8MB */
+ init_stack(&sm_stats.free_page_stack, (getCacheMemMax() / SM_PAGE_SIZE) >> 1);
init_stack(&disk_stats.free_page_stack, 1000);
-#else
+ init_stack(&request_pool.free_page_stack, FD_SETSIZE >> 3);
+ init_stack(&mem_obj_pool.free_page_stack, FD_SETSIZE >> 3);
+#else /* !PURIFY */
/* Declare a zero size page stack so that purify checks for
- * FMRs/UMRs etc.
- */
+ * FMRs/UMRs etc. */
init_stack(&sm_stats.free_page_stack, 0);
init_stack(&disk_stats.free_page_stack, 0);
-#endif
+ init_stack(&request_pool.free_page_stack, 0);
+ init_stack(&mem_obj_pool.free_page_stack, 0);
+#endif /* !PURIFY */
}
-
-/* $Id: store.cc,v 1.65 1996/05/03 22:56:33 wessels Exp $ */
+/*
+ * $Id: store.cc,v 1.66 1996/07/09 03:41:43 wessels Exp $
+ *
+ * DEBUG: section 20 Storeage Manager
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
/*
- * DEBUG: Section 20 store
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
/*
#define WITHOUT_MEMOBJ 0
/* rate of checking expired objects in main loop */
-#define STORE_MAINTAIN_RATE (20)
+#define STORE_MAINTAIN_RATE (10)
#define STORE_BUCKETS (7921)
#define STORE_IN_MEM_BUCKETS (143)
int clashcount; /* # swapfile clashes avoided */
int dupcount; /* # duplicates purged */
time_t start, stop;
- int fast_mode;
+ int speed; /* # Objects per run */
char line_in[4096];
};
+/* initializtion flag */
+int store_rebuilding = STORE_REBUILDING_SLOW;
+
+/* Static Functions */
+static int storeSwapInStart _PARAMS((StoreEntry *, SIH, void *));
+static void destroy_MemObject _PARAMS((MemObject *));
+static void destroy_MemObjectData _PARAMS((MemObject *));
+static void destroy_StoreEntry _PARAMS((StoreEntry *));
+static MemObject *new_MemObject _PARAMS((void));
+static mem_ptr new_MemObjectData _PARAMS((void));
+static StoreEntry *new_StoreEntry _PARAMS((int mem_obj_flag));
+static int storeCheckPurgeMem _PARAMS((StoreEntry * e));
+
+
/* Now, this table is inaccessible to outsider. They have to use a method
* to access a value in internal storage data structure. */
HashID table = 0;
/* hash table for in-memory-only objects */
HashID in_mem_table = 0;
-/* initializtion flag */
-static int ok_write_clean_log = 0;
-
/* current memory storage size */
static unsigned long store_mem_size = 0;
static unsigned long store_mem_high = 0;
static MemObject *new_MemObject()
{
- MemObject *m = NULL;
- m = (MemObject *) xcalloc(1, sizeof(MemObject));
- m->reply = (struct _http_reply *) xcalloc(1, sizeof(struct _http_reply));
+ MemObject *mem = get_free_mem_obj();
+ mem->reply = xcalloc(1, sizeof(struct _http_reply));
meta_data.store_in_mem_objects++;
- debug(20, 3, "new_MemObject: returning %p\n", m);
- return m;
+ meta_data.misc += sizeof(struct _http_reply);
+ debug(20, 3, "new_MemObject: returning %p\n", mem);
+ return mem;
}
static StoreEntry *new_StoreEntry(mem_obj_flag)
{
StoreEntry *e = NULL;
- e = (StoreEntry *) xcalloc(1, sizeof(StoreEntry));
+ e = xcalloc(1, sizeof(StoreEntry));
meta_data.store_entries++;
if (mem_obj_flag)
e->mem_obj = new_MemObject();
return e;
}
-static void destroy_MemObject(m)
- MemObject *m;
+static void destroy_MemObject(mem)
+ MemObject *mem;
{
- debug(20, 3, "destroy_MemObject: destroying %p\n", m);
- safe_free(m->mime_hdr);
- safe_free(m->reply);
- xfree(m);
+ int i;
+ debug(20, 3, "destroy_MemObject: destroying %p\n", mem);
+ destroy_MemObjectData(mem);
+ safe_free(mem->pending);
+ if (mem->client_list) {
+ for (i = 0; i < mem->client_list_size; ++i) {
+ if (mem->client_list[i])
+ safe_free(mem->client_list[i]);
+ }
+ safe_free(mem->client_list);
+ }
+ safe_free(mem->mime_hdr);
+ safe_free(mem->reply);
+ safe_free(mem->e_abort_msg);
+ requestUnlink(mem->request);
+ mem->request = NULL;
+ put_free_mem_obj(mem);
meta_data.store_in_mem_objects--;
+ meta_data.misc -= sizeof(struct _http_reply);
}
static void destroy_StoreEntry(e)
fatal_dump("destroy_StoreEntry: NULL Entry");
if (e->mem_obj)
destroy_MemObject(e->mem_obj);
+ if (e->url) {
+ meta_data.url_strings -= strlen(e->url);
+ safe_free(e->url);
+ } else {
+ debug(20, 3, "destroy_StoreEntry: WARNING! Entry without URL string!\n");
+ }
+ if (BIT_TEST(e->flag, KEY_URL))
+ e->key = NULL;
+ else
+ safe_free(e->key);
xfree(e);
meta_data.store_entries--;
}
return memInit();
}
-static void destroy_MemObjectData(m)
- MemObject *m;
+static void destroy_MemObjectData(mem)
+ MemObject *mem;
{
- debug(20, 3, "destroy_MemObjectData: destroying %p\n", m->data);
- store_mem_size -= m->e_current_len - m->e_lowest_offset;
+ debug(20, 3, "destroy_MemObjectData: destroying %p\n", mem->data);
+ store_mem_size -= mem->e_current_len - mem->e_lowest_offset;
debug(20, 8, "destroy_MemObjectData: Freeing %d in-memory bytes\n",
- m->e_current_len);
+ mem->e_current_len);
debug(20, 8, "destroy_MemObjectData: store_mem_size = %d\n",
store_mem_size);
- if (m->data) {
- m->data->mem_free(m->data);
- m->data = NULL;
+ if (mem->data) {
+ mem->data->mem_free(mem->data);
+ mem->data = NULL;
meta_data.hot_vm--;
}
- m->e_current_len = 0;
+ mem->e_current_len = 0;
}
/* ----- INTERFACE BETWEEN STORAGE MANAGER AND HASH TABLE FUNCTIONS --------- */
void storeSetMemStatus(e, status)
StoreEntry *e;
- int status;
+ mem_status_t status;
{
hash_link *ptr = NULL;
/* -------------------------------------------------------------------------- */
-/* free whole entry */
-void storeFreeEntry(e)
- StoreEntry *e;
-{
- int i;
-
- if (!e)
- fatal_dump("storeFreeEntry: NULL Entry");
-
- debug(20, 3, "storeFreeEntry: Freeing %s\n", e->key);
-
- if (e->mem_obj) {
- destroy_MemObjectData(e->mem_obj);
- e->mem_obj->data = NULL;
- }
- meta_data.url_strings -= strlen(e->url);
- safe_free(e->url);
- if (BIT_TEST(e->flag, KEY_URL))
- e->key = NULL;
- else
- safe_free(e->key);
- if (e->mem_obj) {
- safe_free(e->mem_obj->mime_hdr);
- /* Leave an unzeroed pointer to the abort msg for posterity */
- safe_free(e->mem_obj->e_abort_msg);
- safe_free(e->mem_obj->pending);
- /* look up to free client_list */
- if (e->mem_obj->client_list) {
- for (i = 0; i < e->mem_obj->client_list_size; ++i)
- safe_free(e->mem_obj->client_list[i]);
- safe_free(e->mem_obj->client_list);
- }
- }
- destroy_StoreEntry(e);
-}
-
static char *time_describe(t)
time_t t;
{
debug(20, 3, "storePurgeMem: Freeing memory-copy of %s\n", e->key);
if (e->mem_obj == NULL)
return;
-
if (storeEntryLocked(e)) {
- debug(20, 0, "storePurgeMem: someone (storeGetMemSpace?) is purging a locked object?\n");
+ debug(20, 0, "storePurgeMem: someone is purging a locked object?\n");
debug(20, 0, "%s", storeToString(e));
fatal_dump(NULL);
}
- destroy_MemObjectData(e->mem_obj);
- e->mem_obj->data = NULL;
- debug(20, 8, "storePurgeMem: Freeing %d in-memory bytes\n",
- e->object_len);
- debug(20, 8, "storePurgeMem: store_mem_size = %d\n", store_mem_size);
storeSetMemStatus(e, NOT_IN_MEMORY);
- e->mem_obj->e_current_len = 0;
- /* free up pending list table */
- safe_free(e->mem_obj->pending);
- e->mem_obj->pending_list_size = 0;
- /* free up client list table and entries */
- if (e->mem_obj->client_list) {
- int i;
- for (i = 0; i < e->mem_obj->client_list_size; ++i) {
- if (e->mem_obj->client_list[i])
- safe_free(e->mem_obj->client_list[i]);
- }
- safe_free(e->mem_obj->client_list);
- }
destroy_MemObject(e->mem_obj);
e->mem_obj = NULL;
}
/* lock the object for reading, start swapping in if necessary */
-int storeLockObject(e)
+/* Called by:
+ * icp_hit_or_miss()
+ * storeAbort()
+ * {http,ftp,gopher,wais}Start()
+ */
+int storeLockObject(e, handler, data)
StoreEntry *e;
+ SIH handler;
+ void *data;
{
int swap_in_stat = 0;
int status = 0;
}
e->lastref = squid_curtime;
- /* StoreLockObject() is called during icp_hit_or_miss and once by storeAbort
- * If the object is NOT_IN_MEMORY, fault it in. */
+ /* If the object is NOT_IN_MEMORY, fault it in. */
if ((e->mem_status == NOT_IN_MEMORY) && (e->swap_status == SWAP_OK)) {
/* object is in disk and no swapping daemon running. Bring it in. */
- if ((swap_in_stat = storeSwapInStart(e)) < 0) {
+ if ((swap_in_stat = storeSwapInStart(e, handler, data)) < 0) {
/*
* We couldn't find or couldn't open object's swapfile.
* So, return a -1 here, indicating that we will treat
e->lock_count--;
}
status = swap_in_stat;
+ } else if (e->mem_status == IN_MEMORY && handler) {
+ /* its already in memory, so call the handler */
+ (*handler) (0, data);
+ } else if (handler) {
+ /* The object is probably in state SWAPPING_IN, not much we can do.
+ * Instead of returning failure here, we should have a list of complete
+ * handlers which we could append to... */
+ (*handler) (1, data);
}
return status;
}
{
if (e->flag & RELEASE_REQUEST)
return;
+ if (!storeEntryLocked(e))
+ fatal_dump("Somebody called storeReleaseRequest on an unlocked entry");
debug(20, 3, "storeReleaseRequest: FOR '%s'\n", e->key ? e->key : e->url);
e->flag |= RELEASE_REQUEST;
}
/* unlock object, return -1 if object get released after unlock
* otherwise lock_count */
-
int storeUnlockObject(e)
StoreEntry *e;
{
- int e_lock_count;
-
+ int lock_count;
if ((int) e->lock_count > 0)
e->lock_count--;
}
debug(20, 3, "storeUnlockObject: key '%s' count=%d\n", e->key, e->lock_count);
+ if (e->lock_count)
+ return e->lock_count;
+
/* Prevent UMR if we end up freeing the entry */
- e_lock_count = (int) e->lock_count;
+ lock_count = (int) e->lock_count;
- if (e->lock_count == 0) {
- if (e->flag & RELEASE_REQUEST) {
- storeRelease(e);
- } else if (e->flag & ABORT_MSG_PENDING) {
- /* This is where the negative cache gets storeAppended */
- /* Briefly lock to replace content with abort message */
- e->lock_count++;
- destroy_MemObjectData(e->mem_obj);
- e->object_len = 0;
- e->mem_obj->data = new_MemObjectData();
- storeAppend(e, e->mem_obj->e_abort_msg, strlen(e->mem_obj->e_abort_msg));
- e->object_len = e->mem_obj->e_current_len
- = strlen(e->mem_obj->e_abort_msg);
- BIT_RESET(e->flag, ABORT_MSG_PENDING);
- e->lock_count--;
- }
+ if (e->flag & RELEASE_REQUEST) {
+ storeRelease(e);
+ } else if (e->flag & ABORT_MSG_PENDING) {
+ /* This is where the negative cache gets storeAppended */
+ /* Briefly lock to replace content with abort message */
+ e->lock_count++;
+ destroy_MemObjectData(e->mem_obj);
+ e->object_len = 0;
+ e->mem_obj->data = new_MemObjectData();
+ storeAppend(e, e->mem_obj->e_abort_msg, strlen(e->mem_obj->e_abort_msg));
+ e->object_len = e->mem_obj->e_current_len
+ = strlen(e->mem_obj->e_abort_msg);
+ BIT_RESET(e->flag, ABORT_MSG_PENDING);
+ e->lock_count--;
+ } else if (storeCheckPurgeMem(e)) {
+ storePurgeMem(e);
}
- return e_lock_count;
-
+ return lock_count;
}
/* Lookup an object in the cache.
char *storeGeneratePrivateKey(url, method, num)
char *url;
- int method;
+ method_t method;
int num;
{
if (num == 0)
char *storeGeneratePublicKey(url, method)
char *url;
- int method;
+ method_t method;
{
debug(20, 3, "storeGeneratePublicKey: type=%d %s\n", method, url);
switch (method) {
return key_temp_buffer;
/* NOTREACHED */
break;
+ case METHOD_PUT:
+ sprintf(key_temp_buffer, "/put/%s", url);
+ return key_temp_buffer;
+ /* NOTREACHED */
+ break;
case METHOD_HEAD:
sprintf(key_temp_buffer, "/head/%s", url);
return key_temp_buffer;
newkey = storeGeneratePublicKey(e->url, e->method);
while ((table_entry = hash_lookup(table, newkey))) {
- debug(20, 0, "storeSetPublicKey: Making old '%s' private.\n", newkey);
+ debug(20, 3, "storeSetPublicKey: Making old '%s' private.\n", newkey);
e2 = (StoreEntry *) table_entry;
storeSetPrivateKey(e2);
- storeReleaseRequest(e2);
+ storeRelease(e2);
if (loop_detect++ == 10)
fatal_dump("storeSetPublicKey() is looping!!");
newkey = storeGeneratePublicKey(e->url, e->method);
char *url;
char *req_hdr;
int flags;
- int method;
+ method_t method;
{
StoreEntry *e = NULL;
- MemObject *m = NULL;
+ MemObject *mem = NULL;
debug(20, 3, "storeCreateEntry: '%s' icp flags=%x\n", url, flags);
if (meta_data.hot_vm > store_hotobj_high)
storeGetMemSpace(0, 1);
e = new_StoreEntry(WITH_MEMOBJ);
- m = e->mem_obj;
+ e->lock_count = 1; /* Note lock here w/o calling storeLock() */
+ mem = e->mem_obj;
e->url = xstrdup(url);
meta_data.url_strings += strlen(url);
e->method = method;
if (req_hdr)
- m->mime_hdr = xstrdup(req_hdr);
+ mem->mime_hdr = xstrdup(req_hdr);
if (BIT_TEST(flags, REQ_NOCACHE))
BIT_SET(e->flag, REFRESH_REQUEST);
if (BIT_TEST(flags, REQ_CACHABLE)) {
storeSetMemStatus(e, NOT_IN_MEMORY);
e->swap_status = NO_SWAP;
e->swap_file_number = -1;
- e->lock_count = 0;
- m->data = new_MemObjectData();
+ mem->data = new_MemObjectData();
e->refcount = 0;
e->lastref = squid_curtime;
e->timestamp = 0; /* set in storeSwapOutHandle() */
- e->ping_status = NOPING;
+ e->ping_status = PING_NONE;
/* allocate pending list */
- m->pending_list_size = MIN_PENDING;
- m->pending = (struct pentry **)
- xcalloc(m->pending_list_size, sizeof(struct pentry *));
+ mem->pending_list_size = MIN_PENDING;
+ mem->pending = (struct pentry **)
+ xcalloc(mem->pending_list_size, sizeof(struct pentry *));
/* allocate client list */
- m->client_list_size = MIN_CLIENT;
- m->client_list = (ClientStatusEntry **)
- xcalloc(m->client_list_size, sizeof(ClientStatusEntry *));
+ mem->client_list_size = MIN_CLIENT;
+ mem->client_list = (ClientStatusEntry **)
+ xcalloc(mem->client_list_size, sizeof(ClientStatusEntry *));
/* storeLog(STORE_LOG_CREATE, e); */
return e;
/* if you call this you'd better be sure file_number is not
* already in use! */
- meta_data.store_entries++;
meta_data.url_strings += strlen(url);
e = new_StoreEntry(WITHOUT_MEMOBJ);
e->lastref = squid_curtime;
e->timestamp = (u_num32) timestamp;
e->expires = (u_num32) expires;
- e->ping_status = NOPING;
+ e->ping_status = PING_NONE;
return e;
}
debug(20, 3, "storeRegister: FD %d '%s'\n", fd, e->key);
- pe = (PendingEntry *) xcalloc(1, sizeof(PendingEntry));
+ pe = xcalloc(1, sizeof(PendingEntry));
pe->fd = fd;
pe->handler = handler;
pe->data = data;
e->mem_obj->pending_list_size += MIN_PENDING;
/* allocate, and copy old pending list over to the new one */
- tmp = (struct pentry **) xcalloc(e->mem_obj->pending_list_size,
+ tmp = xcalloc(e->mem_obj->pending_list_size,
sizeof(struct pentry *));
for (j = 0; j < old_size; j++)
tmp[j] = e->mem_obj->pending[j];
int storeGetLowestReaderOffset(entry)
StoreEntry *entry;
{
- MemObject *m = entry->mem_obj;
- int lowest = m->e_current_len;
+ MemObject *mem = entry->mem_obj;
+ int lowest = mem->e_current_len;
int i;
- for (i = 0; i < m->client_list_size; i++) {
- if (m->client_list[i] == NULL)
+ for (i = 0; i < mem->client_list_size; i++) {
+ if (mem->client_list[i] == NULL)
continue;
- if (m->client_list[i]->last_offset < lowest)
- lowest = m->client_list[i]->last_offset;
+ if (mem->client_list[i]->last_offset < lowest)
+ lowest = mem->client_list[i]->last_offset;
}
return lowest;
}
-
/* Call to delete behind upto "target lowest offset"
* also, update e_lowest_offset */
void storeDeleteBehind(e)
StoreEntry *e;
{
- MemObject *m = e->mem_obj;
+ MemObject *mem = e->mem_obj;
int free_up_to;
int target_offset;
debug(20, 3, "storeDeleteBehind: Object: %s\n", e->key);
debug(20, 3, "storeDeleteBehind: Original Lowest Offset: %d\n",
- m->e_lowest_offset);
+ mem->e_lowest_offset);
- free_up_to = m->e_lowest_offset;
+ free_up_to = mem->e_lowest_offset;
target_offset = storeGetLowestReaderOffset(e);
debug(20, 3, "storeDeleteBehind: target offset: %d\n", target_offset);
if (target_offset) {
- free_up_to = (int) m->data->mem_free_data_upto(m->data, target_offset);
+ free_up_to = (int) mem->data->mem_free_data_upto(mem->data, target_offset);
debug(20, 3, "--> Object is freed upto : %d\n", free_up_to);
- store_mem_size -= free_up_to - m->e_lowest_offset;
+ store_mem_size -= free_up_to - mem->e_lowest_offset;
}
debug(20, 3, "storeDeleteBehind: New lowest offset: %d\n", free_up_to);
- m->e_lowest_offset = free_up_to;
+ mem->e_lowest_offset = free_up_to;
}
/* Call handlers waiting for data to be appended to E. */
va_end(args);
}
-
/* add directory to swap disk */
int storeAddSwapDisk(path)
char *path;
StoreEntry *e;
int offset_notused;
{
+ MemObject *mem = e->mem_obj;
debug(20, 2, "storeSwapInHandle: '%s'\n", e->key);
if ((flag < 0) && (flag != DISK_EOF)) {
debug(20, 0, "storeSwapInHandle: SwapIn failure (err code = %d).\n", flag);
- put_free_8k_page(e->mem_obj->e_swap_buf);
+ put_free_8k_page(mem->e_swap_buf);
storeSetMemStatus(e, NOT_IN_MEMORY);
- file_close(e->mem_obj->swap_fd);
+ file_close(mem->swap_fd);
swapInError(-1, e); /* Invokes storeAbort() and completes the I/O */
+ if (mem->swapin_complete_handler) {
+ (*mem->swapin_complete_handler) (2, mem->swapin_complete_data);
+ mem->swapin_complete_handler = NULL;
+ mem->swapin_complete_data = NULL;
+ }
return -1;
}
- debug(20, 5, "storeSwapInHandle: e->swap_offset = %d\n",
- e->mem_obj->swap_offset);
- debug(20, 5, "storeSwapInHandle: len = %d\n",
- len);
- debug(20, 5, "storeSwapInHandle: e->e_current_len = %d\n",
- e->mem_obj->e_current_len);
- debug(20, 5, "storeSwapInHandle: e->object_len = %d\n",
- e->object_len);
+ debug(20, 5, "storeSwapInHandle: e->swap_offset = %d\n", mem->swap_offset);
+ debug(20, 5, "storeSwapInHandle: len = %d\n", len);
+ debug(20, 5, "storeSwapInHandle: e->e_current_len = %d\n", mem->e_current_len);
+ debug(20, 5, "storeSwapInHandle: e->object_len = %d\n", e->object_len);
/* always call these, even if len == 0 */
- e->mem_obj->swap_offset += len;
+ mem->swap_offset += len;
storeAppend(e, buf, len);
- if (e->mem_obj->e_current_len < e->object_len && flag != DISK_EOF) {
+ if (mem->e_current_len < e->object_len && flag != DISK_EOF) {
/* some more data to swap in, reschedule */
- file_read(e->mem_obj->swap_fd,
- e->mem_obj->e_swap_buf,
+ file_read(mem->swap_fd,
+ mem->e_swap_buf,
SWAP_BUF,
- e->mem_obj->swap_offset,
+ mem->swap_offset,
(FILE_READ_HD) storeSwapInHandle,
(void *) e);
} else {
/* complete swapping in */
storeSetMemStatus(e, IN_MEMORY);
- put_free_8k_page(e->mem_obj->e_swap_buf);
- file_close(e->mem_obj->swap_fd);
+ put_free_8k_page(mem->e_swap_buf);
+ file_close(mem->swap_fd);
storeLog(STORE_LOG_SWAPIN, e);
debug(20, 5, "storeSwapInHandle: SwapIn complete: <URL:%s> from %s.\n",
e->url, storeSwapFullPath(e->swap_file_number, NULL));
- if (e->mem_obj->e_current_len != e->object_len) {
+ if (mem->e_current_len != e->object_len) {
debug(20, 0, "storeSwapInHandle: WARNING! Object size mismatch.\n");
debug(20, 0, " --> <URL:%s>\n", e->url);
debug(20, 0, " --> Expecting %d bytes from file: %s\n", e->object_len,
storeSwapFullPath(e->swap_file_number, NULL));
debug(20, 0, " --> Only read %d bytes\n",
- e->mem_obj->e_current_len);
+ mem->e_current_len);
+ }
+ if (mem->swapin_complete_handler) {
+ (*mem->swapin_complete_handler) (0, mem->swapin_complete_data);
+ mem->swapin_complete_handler = NULL;
+ mem->swapin_complete_data = NULL;
}
if (e->flag & RELEASE_REQUEST)
storeRelease(e);
}
/* start swapping in */
-int storeSwapInStart(e)
+static int storeSwapInStart(e, swapin_complete_handler, swapin_complete_data)
StoreEntry *e;
+ SIH swapin_complete_handler;
+ void *swapin_complete_data;
{
int fd;
char *path = NULL;
path = storeSwapFullPath(e->swap_file_number, NULL);
if ((fd = file_open(path, NULL, O_RDONLY)) < 0) {
- debug(20, 0, "storeSwapInStart: Unable to open swapfile: %s\n",
- path);
- debug(20, 0, "storeSwapInStart: --> for <URL:%s>\n",
- e->url);
+ debug(20, 0, "storeSwapInStart: Failed for '%s'\n", e->url);
storeSetMemStatus(e, NOT_IN_MEMORY);
/* Invoke a store abort that should free the memory object */
return -1;
e->mem_obj->swap_offset,
(FILE_READ_HD) storeSwapInHandle,
(void *) e);
+ e->mem_obj->swapin_complete_handler = swapin_complete_handler;
+ e->mem_obj->swapin_complete_data = swapin_complete_data;
return 0;
}
e->swap_status = NO_SWAP;
put_free_8k_page(page_ptr);
file_close(fd);
- storeReleaseRequest(e);
+ storeRelease(e);
if (e->swap_file_number != -1) {
file_map_bit_reset(e->swap_file_number);
safeunlink(filename, 0); /* remove it */
swaplog_lock,
NULL,
NULL);
+ CacheInfo->proto_newobject(CacheInfo,
+ CacheInfo->proto_id(e->url),
+ e->object_len,
+ FALSE);
/* check if it's request to be released. */
if (e->flag & RELEASE_REQUEST)
storeRelease(e);
+ else if (storeCheckPurgeMem(e))
+ storePurgeMem(e);
return;
}
/* write some more data, reschedule itself. */
off_t size;
int delta;
int sfileno = 0;
-
- if (!fgets(data->line_in, 4095, data->log))
- return 0;
-
- if ((++data->linecount & 0xFFF) == 0)
- debug(20, 1, " %7d Lines read so far.\n", data->linecount);
-
- debug(20, 10, "line_in: %s", data->line_in);
- if ((data->line_in[0] == '\0') || (data->line_in[0] == '\n') ||
- (data->line_in[0] == '#'))
- return 1; /* skip bad lines */
-
- url[0] = log_swapfile[0] = '\0';
- expires = squid_curtime;
-
- scan3 = 0;
- size = 0;
- if (sscanf(data->line_in, "%s %s %d %d %d",
- log_swapfile, url, &scan1, &scan2, &scan3) != 5) {
- if (opt_unlink_on_reload && log_swapfile[0])
- safeunlink(log_swapfile, 0);
- return 1;
- }
- expires = (time_t) scan1;
- timestamp = (time_t) scan2;
- size = (off_t) scan3;
- if ((t = strrchr(log_swapfile, '/')))
- sfileno = atoi(t + 1);
- else
- sfileno = atoi(log_swapfile);
- storeSwapFullPath(sfileno, swapfile);
-
- /*
- * Note that swapfile may be different than log_swapfile if
- * another cache_dir is added.
- */
-
- if (!data->fast_mode) {
- if (stat(swapfile, &sb) < 0) {
- if (expires < squid_curtime) {
- debug(20, 3, "storeRebuildFromDisk: Expired: <URL:%s>\n", url);
- if (opt_unlink_on_reload)
- safeunlink(swapfile, 1);
- data->expcount++;
- } else {
- debug(20, 3, "storeRebuildFromDisk: Swap file missing: <URL:%s>: %s: %s.\n", url, swapfile, xstrerror());
+ int count;
+
+ /* load a number of objects per invocation */
+ for (count = 0; count < data->speed; count++) {
+ if (!fgets(data->line_in, 4095, data->log))
+ return 0; /* We are done */
+
+ if ((++data->linecount & 0xFFF) == 0)
+ debug(20, 1, " %7d Lines read so far.\n", data->linecount);
+
+ debug(20, 10, "line_in: %s", data->line_in);
+ if ((data->line_in[0] == '\0') || (data->line_in[0] == '\n') ||
+ (data->line_in[0] == '#'))
+ continue; /* skip bad lines */
+
+ url[0] = log_swapfile[0] = '\0';
+ expires = squid_curtime;
+
+ scan3 = 0;
+ size = 0;
+ if (sscanf(data->line_in, "%s %s %d %d %d",
+ log_swapfile, url, &scan1, &scan2, &scan3) != 5) {
+ if (opt_unlink_on_reload && log_swapfile[0])
+ safeunlink(log_swapfile, 0);
+ continue;
+ }
+ expires = (time_t) scan1;
+ timestamp = (time_t) scan2;
+ size = (off_t) scan3;
+ if ((t = strrchr(log_swapfile, '/')))
+ sfileno = atoi(t + 1);
+ else
+ sfileno = atoi(log_swapfile);
+ storeSwapFullPath(sfileno, swapfile);
+
+ /*
+ * Note that swapfile may be different than log_swapfile if
+ * another cache_dir is added.
+ */
+
+ if (store_rebuilding != STORE_REBUILDING_FAST) {
+ if (stat(swapfile, &sb) < 0) {
+ if (expires < squid_curtime) {
+ debug(20, 3, "storeRebuildFromDisk: Expired: <URL:%s>\n", url);
+ if (opt_unlink_on_reload)
+ safeunlink(swapfile, 1);
+ data->expcount++;
+ } else {
+ debug(20, 3, "storeRebuildFromDisk: Swap file missing: <URL:%s>: %s: %s.\n", url, swapfile, xstrerror());
+ if (opt_unlink_on_reload)
+ safeunlink(log_swapfile, 1);
+ }
+ continue;
+ }
+ /* Empty swap file? */
+ if (sb.st_size == 0) {
if (opt_unlink_on_reload)
safeunlink(log_swapfile, 1);
+ continue;
}
- return 1;
- }
- /* Empty swap file? */
- if (sb.st_size == 0) {
- if (opt_unlink_on_reload)
- safeunlink(log_swapfile, 1);
- return 1;
- }
- /* timestamp might be a little bigger than sb.st_mtime */
- delta = (int) (timestamp - sb.st_mtime);
- if (delta > REBUILD_TIMESTAMP_DELTA_MAX || delta < 0) {
- /* this log entry doesn't correspond to this file */
- data->clashcount++;
- return 1;
+ /* timestamp might be a little bigger than sb.st_mtime */
+ delta = (int) (timestamp - sb.st_mtime);
+ if (delta > REBUILD_TIMESTAMP_DELTA_MAX || delta < 0) {
+ /* this log entry doesn't correspond to this file */
+ data->clashcount++;
+ continue;
+ }
+ /* Wrong size? */
+ if (sb.st_size != size) {
+ /* this log entry doesn't correspond to this file */
+ data->clashcount++;
+ continue;
+ }
+ timestamp = sb.st_mtime;
+ debug(20, 10, "storeRebuildFromDisk: swap file exists: <URL:%s>: %s\n",
+ url, swapfile);
}
- /* Wrong size? */
- if (sb.st_size != size) {
- /* this log entry doesn't correspond to this file */
- data->clashcount++;
- return 1;
+ if ((e = storeGet(url))) {
+ if (e->timestamp > timestamp) {
+ /* already have a newer object in memory, throw old one away */
+ debug(20, 3, "storeRebuildFromDisk: Replaced: %s\n", url);
+ if (opt_unlink_on_reload)
+ safeunlink(swapfile, 1);
+ data->dupcount++;
+ continue;
+ }
+ debug(20, 6, "storeRebuildFromDisk: Duplicate: <URL:%s>\n", url);
+ storeRelease(e);
+ data->objcount--;
+ data->dupcount++;
}
- timestamp = sb.st_mtime;
- debug(20, 10, "storeRebuildFromDisk: swap file exists: <URL:%s>: %s\n",
- url, swapfile);
- }
- if ((e = storeGet(url))) {
- if (e->timestamp > timestamp) {
- /* already have a newer object in memory, throw old one away */
- debug(20, 3, "storeRebuildFromDisk: Replaced: %s\n", url);
+ if (expires < squid_curtime) {
+ debug(20, 3, "storeRebuildFromDisk: Expired: <URL:%s>\n", url);
if (opt_unlink_on_reload)
safeunlink(swapfile, 1);
- data->dupcount++;
- return 1;
+ data->expcount++;
+ continue;
}
- debug(20, 6, "storeRebuildFromDisk: Duplicate: <URL:%s>\n", url);
- storeRelease(e);
- data->objcount--;
- data->dupcount++;
- }
- if (expires < squid_curtime) {
- debug(20, 3, "storeRebuildFromDisk: Expired: <URL:%s>\n", url);
- if (opt_unlink_on_reload)
- safeunlink(swapfile, 1);
- data->expcount++;
- return 1;
- }
- /* Is the swap file number already taken? */
- if (file_map_bit_test(sfileno)) {
- /* Yes is is, we can't use this swapfile */
- debug(20, 1, "storeRebuildFromDisk: Line %d Active clash: file #%d\n",
- data->linecount,
- sfileno);
- debug(20, 3, "storeRebuildFromDisk: --> <URL:%s>\n", url);
- /* don't unlink the file! just skip this log entry */
- data->clashcount++;
- return 1;
+ /* Is the swap file number already taken? */
+ if (file_map_bit_test(sfileno)) {
+ /* Yes it is, we can't use this swapfile */
+ debug(20, 2, "storeRebuildFromDisk: Line %d Active clash: file #%d\n",
+ data->linecount,
+ sfileno);
+ debug(20, 3, "storeRebuildFromDisk: --> <URL:%s>\n", url);
+ /* don't unlink the file! just skip this log entry */
+ data->clashcount++;
+ continue;
+ }
+ /* update store_swap_size */
+ store_swap_size += (int) ((size + 1023) >> 10);
+ data->objcount++;
+
+ sprintf(logmsg, "%s %s %d %d %d\n",
+ swapfile,
+ url,
+ (int) expires,
+ (int) timestamp,
+ (int) size);
+ /* Automatically freed by file_write because no-handlers */
+ file_write(swaplog_fd,
+ xstrdup(logmsg),
+ strlen(logmsg),
+ swaplog_lock,
+ NULL,
+ NULL);
+ storeAddDiskRestore(url,
+ sfileno,
+ (int) size,
+ expires,
+ timestamp);
+ CacheInfo->proto_newobject(CacheInfo,
+ CacheInfo->proto_id(url),
+ (int) size,
+ TRUE);
}
- /* update store_swap_size */
- store_swap_size += (int) ((size + 1023) >> 10);
- data->objcount++;
-
- sprintf(logmsg, "%s %s %d %d %d\n",
- swapfile,
- url,
- (int) expires,
- (int) timestamp,
- (int) size);
- /* Automatically freed by file_write because no-handlers */
- file_write(swaplog_fd,
- xstrdup(logmsg),
- strlen(logmsg),
- swaplog_lock,
- NULL,
- NULL);
- storeAddDiskRestore(url,
- sfileno,
- (int) size,
- expires,
- timestamp);
- CacheInfo->proto_newobject(CacheInfo,
- CacheInfo->proto_id(url),
- (int) size,
- TRUE);
return 1;
}
r > 0 ? r : 0, (double) data->objcount / (r > 0 ? r : 1));
debug(20, 1, " store_swap_size = %dk\n", store_swap_size);
- ok_write_clean_log = 1;
+ store_rebuilding = STORE_NOT_REBUILDING;
fclose(data->log);
safe_free(data);
if (stat(swaplog_file, &sb) < 0) {
debug(20, 1, "storeRebuildFromDisk: No log file\n");
- ok_write_clean_log = 1;
+ store_rebuilding = STORE_NOT_REBUILDING;
return;
}
data = xcalloc(1, sizeof(*data));
if (stat(tmp_filename, &sb) >= 0) {
last_clean = sb.st_mtime;
if (stat(swaplog_file, &sb) >= 0)
- data->fast_mode = (sb.st_mtime <= last_clean) ? 1 : 0;
+ store_rebuilding = (sb.st_mtime <= last_clean) ?
+ STORE_REBUILDING_FAST : STORE_REBUILDING_SLOW;
}
+ /* Remove timestamp in case we crash during rebuild */
+ safeunlink(tmp_filename, 1);
/* close the existing write-only swaplog, and open a temporary
* write-only swaplog */
if (file_write_unlock(swaplog_fd, swaplog_lock) != DISK_OK)
if (swaplog_fd > -1)
file_close(swaplog_fd);
sprintf(tmp_filename, "%s.new", swaplog_file);
- swaplog_fd = file_open(tmp_filename, NULL, O_WRONLY | O_CREAT | O_APPEND);
+ swaplog_fd = file_open(tmp_filename, NULL,
+ O_WRONLY | O_CREAT | O_APPEND | O_TRUNC);
debug(20, 3, "swaplog_fd %d is now '%s'\n", swaplog_fd, tmp_filename);
if (swaplog_fd < 0) {
debug(20, 0, "storeStartRebuildFromDisk: %s: %s\n",
fatal(tmp_error_buf);
}
debug(20, 3, "data->log %d is now '%s'\n", fileno(data->log), swaplog_file);
- if (data->fast_mode)
+ if (store_rebuilding == STORE_REBUILDING_FAST)
debug(20, 1, "Rebuilding in FAST MODE.\n");
memset(data->line_in, '\0', 4096);
+ data->speed = store_rebuilding == STORE_REBUILDING_FAST ? 50 : 5;
/* Start reading the log file */
- runInBackground("storeRebuild",
- (int (*)(void *)) storeDoRebuildFromDisk,
- data,
- (void (*)(void *)) storeRebuiltFromDisk);
+ if (opt_foreground_rebuild) {
+ while (storeDoRebuildFromDisk(data));
+ storeRebuiltFromDisk(data);
+ } else {
+ runInBackground("storeRebuild",
+ (int (*)(void *)) storeDoRebuildFromDisk,
+ data,
+ (void (*)(void *)) storeRebuiltFromDisk);
+ }
}
/* return current swap size in kilo-bytes */
storeSwapOutStart(e);
/* free up incoming MIME */
safe_free(e->mem_obj->mime_hdr);
- CacheInfo->proto_newobject(CacheInfo, CacheInfo->proto_id(e->url),
- e->object_len, FALSE);
if (e->flag & RELEASE_REQUEST)
storeRelease(e);
}
*/
BIT_SET(e->flag, ENTRY_DISPATCHED);
- storeLockObject(e);
+ storeLockObject(e, NULL, NULL);
/* Count bytes faulted through cache but not moved to disk */
CacheInfo->proto_touchobject(CacheInfo, CacheInfo->proto_id(e->url),
break;
} /* for */
+#ifdef LOTSA_DEBUGGING
/* end of candidate selection */
- debug(20, 2, "storeGetSwapSpace: Current Size: %7d kbytes\n", store_swap_size);
- debug(20, 2, "storeGetSwapSpace: High W Mark: %7d kbytes\n", store_swap_high);
- debug(20, 2, "storeGetSwapSpace: Low W Mark: %7d kbytes\n", store_swap_low);
- debug(20, 2, "storeGetSwapSpace: Entry count: %7d items\n", meta_data.store_entries);
- debug(20, 2, "storeGetSwapSpace: Scanned: %7d items\n", scanned);
- debug(20, 2, "storeGetSwapSpace: Expired: %7d items\n", expired);
- debug(20, 2, "storeGetSwapSpace: Locked: %7d items\n", locked);
- debug(20, 2, "storeGetSwapSpace: Locked Space: %7d bytes\n", locked_size);
- debug(20, 2, "storeGetSwapSpace: Scan in array: %7d bytes\n", scan_in_objs);
- debug(20, 2, "storeGetSwapSpace: LRU candidate: %7d items\n", LRU_list->index);
+ debug(20, 2, "storeGetSwapSpace: Current Size: %7d kbytes\n",
+ store_swap_size);
+ debug(20, 2, "storeGetSwapSpace: High W Mark: %7d kbytes\n",
+ store_swap_high);
+ debug(20, 2, "storeGetSwapSpace: Low W Mark: %7d kbytes\n",
+ store_swap_low);
+ debug(20, 2, "storeGetSwapSpace: Entry count: %7d items\n",
+ meta_data.store_entries);
+ debug(20, 2, "storeGetSwapSpace: Visited: %7d buckets\n",
+ i + 1);
+ debug(20, 2, "storeGetSwapSpace: Scanned: %7d items\n",
+ scanned);
+ debug(20, 2, "storeGetSwapSpace: Expired: %7d items\n",
+ expired);
+ debug(20, 2, "storeGetSwapSpace: Locked: %7d items\n",
+ locked);
+ debug(20, 2, "storeGetSwapSpace: Locked Space: %7d bytes\n",
+ locked_size);
+ debug(20, 2, "storeGetSwapSpace: Scan in array: %7d bytes\n",
+ scan_in_objs);
+ debug(20, 2, "storeGetSwapSpace: LRU candidate: %7d items\n",
+ LRU_list->index);
+#endif /* LOTSA_DEBUGGING */
/* Although all expired objects removed, still didn't recover enough */
/* space. Kick LRU out until we have enough swap space */
swap_help = 0;
}
- debug(20, 2, "storeGetSwapSpace: Finished, %d objects removed.\n", removed);
+ getCurrentTime(); /* we may have taken more than one second */
+ debug(20, 2, "Removed %d objects\n", removed);
return 0;
}
}
}
}
+ if (store_rebuilding == STORE_REBUILDING_FAST) {
+ debug(20, 2, "storeRelease: Delaying release until store is rebuilt: '%s'\n",
+ e->key ? e->key : e->url ? e->url : "NO URL");
+ storeExpireNow(e);
+ storeSetPrivateKey(e);
+ return -1;
+ }
if (e->key)
debug(20, 5, "storeRelease: Release object key: %s\n", e->key);
else
debug(20, 5, "storeRelease: Release anonymous object\n");
if (e->swap_status == SWAP_OK && (e->swap_file_number > -1)) {
- (void) safeunlink(storeSwapFullPath(e->swap_file_number, NULL), 0);
+ (void) safeunlink(storeSwapFullPath(e->swap_file_number, NULL), 1);
file_map_bit_reset(e->swap_file_number);
e->swap_file_number = -1;
store_swap_size -= (e->object_len + 1023) >> 10;
+ CacheInfo->proto_purgeobject(CacheInfo,
+ CacheInfo->proto_id(e->url),
+ e->object_len);
}
- /* Discard byte count */
- CacheInfo->proto_purgeobject(CacheInfo,
- CacheInfo->proto_id(e->url),
- e->object_len);
if (hptr)
storeHashDelete(hptr);
storeLog(STORE_LOG_RELEASE, e);
- storeFreeEntry(e);
+ destroy_StoreEntry(e);
return 0;
}
debug(20, 0, "%s", storeToString(e));
fatal_dump(NULL);
}
- return ((e->lock_count) ||
- (e->store_status == STORE_PENDING) ||
- (e->swap_status == SWAPPING_OUT) ||
- (e->mem_status == SWAPPING_IN)
- );
+ if (e->lock_count)
+ return 1;
+ if (e->swap_status == SWAPPING_OUT)
+ return 1;
+ if (e->mem_status == SWAPPING_IN)
+ return 1;
+ return 0;
}
/* use this for internal call only */
if (i == e->mem_obj->client_list_size) {
/* have to expand client_list */
e->mem_obj->client_list_size += MIN_CLIENT;
- e->mem_obj->client_list = (ClientStatusEntry **) xrealloc(e->mem_obj->client_list, e->mem_obj->client_list_size * sizeof(ClientStatusEntry *));
+ e->mem_obj->client_list = xrealloc(e->mem_obj->client_list, e->mem_obj->client_list_size * sizeof(ClientStatusEntry *));
}
} else {
e->mem_obj->client_list_size += MIN_CLIENT;
- e->mem_obj->client_list = (ClientStatusEntry **) xcalloc(e->mem_obj->client_list_size, sizeof(ClientStatusEntry *));
+ e->mem_obj->client_list = xcalloc(e->mem_obj->client_list_size, sizeof(ClientStatusEntry *));
i = 0;
}
- e->mem_obj->client_list[i] = (ClientStatusEntry *) xcalloc(1, sizeof(ClientStatusEntry));
+ e->mem_obj->client_list[i] = xcalloc(1, sizeof(ClientStatusEntry));
e->mem_obj->client_list[i]->fd = fd;
e->mem_obj->client_list[i]->last_offset = last_offset;
}
int storeEntryValidToSend(e)
StoreEntry *e;
{
+ /* XXX I think this is not needed since storeCheckPurgeMem() has
+ * been added. If we never see output from this, lets delete it
+ * in a future version -DW */
+ if ((e->mem_status == NOT_IN_MEMORY) && /* Not in memory */
+ (e->swap_status != SWAP_OK) && /* Not on disk */
+ (e->store_status != STORE_PENDING) /* Not being fetched */
+ ) {
+ debug(20, 0, "storeEntryValidToSend: Invalid object detected!\n");
+ debug(20, 0, "storeEntryValidToSend: Entry Dump:\n%s\n", storeToString(e));
+ return 0;
+ }
if (squid_curtime < e->expires)
return 1;
- if (e->expires == 0 && e->store_status == STORE_PENDING)
+ if (e->expires == 0 && e->store_status == STORE_PENDING && e->mem_status != NOT_IN_MEMORY)
return 1;
return 0;
}
}
swaplog_lock = file_write_lock(swaplog_fd);
- if (!zap_disk_store) {
- ok_write_clean_log = 0;
+ if (!zap_disk_store)
storeStartRebuildFromDisk();
- } else {
- ok_write_clean_log = 1;
- }
+ else
+ store_rebuilding = STORE_NOT_REBUILDING;
if (dir_created || zap_disk_store)
storeCreateSwapSubDirs();
return (strcmp(url1, url2));
}
-int parse_file_number(s)
- char *s;
-{
- int len;
-
-
- for (len = strlen(s); (len >= 0); --len) {
- if (s[len] == '/') {
- return (atoi(&s[len + 1]));
- }
- }
- debug(20, 1, "parse_file_number: Could not determine the swap file number from %s.\n", s);
- return (0);
-}
-
/*
* This routine is to be called by main loop in main.c.
* It removes expired objects on only one bucket for each time called.
*/
int storeMaintainSwapSpace()
{
- static int loop_count = 0;
+ static time_t last_time = 0;
static unsigned int bucket = 0;
hash_link *link_ptr = NULL, *next = NULL;
StoreEntry *e = NULL;
int rm_obj = 0;
+ /* We can't delete objects while rebuilding swap */
+ if (store_rebuilding == STORE_REBUILDING_FAST)
+ return -1;
+
/* Scan row of hash table each second and free storage if we're
* over the high-water mark */
storeGetSwapSpace(0);
/* Purges expired objects, check one bucket on each calling */
- if (loop_count++ >= STORE_MAINTAIN_RATE) {
- loop_count = 0;
+ if (squid_curtime - last_time >= STORE_MAINTAIN_RATE) {
+ last_time = squid_curtime;
if (bucket >= STORE_BUCKETS)
bucket = 0;
link_ptr = hash_get_bucket(table, bucket++);
link_ptr = next;
}
}
+ debug(20, rm_obj ? 2 : 3, "Removed %d expired objects\n", rm_obj);
return rm_obj;
}
static char swapfilename[MAX_FILE_NAME_LEN];
FILE *fp = NULL;
int n = 0;
+ int x = 0;
time_t start, stop, r;
- if (!ok_write_clean_log) {
+ if (store_rebuilding) {
debug(20, 1, "storeWriteCleanLog: Not currently OK to rewrite swap log.\n");
debug(20, 1, "storeWriteCleanLog: Operation aborted.\n");
return 0;
if (e->object_len <= 0)
continue;
storeSwapFullPath(e->swap_file_number, swapfilename);
- fprintf(fp, "%s %s %d %d %d\n",
+ x = fprintf(fp, "%s %s %d %d %d\n",
swapfilename, e->url, (int) e->expires, (int) e->timestamp,
e->object_len);
+ if (x < 0) {
+ debug(20, 0, "storeWriteCleanLog: %s: %s", tmp_filename, xstrerror());
+ debug(20, 0, "storeWriteCleanLog: Current swap logfile not replaced.\n");
+ fclose(fp);
+ safeunlink(tmp_filename, 0);
+ return 0;
+ }
if ((++n & 0xFFF) == 0) {
getCurrentTime();
debug(20, 1, " %7d lines written so far.\n", n);
}
}
- fclose(fp);
-
+ if (fclose(fp) < 0) {
+ debug(20, 0, "storeWriteCleanLog: %s: %s", tmp_filename, xstrerror());
+ debug(20, 0, "storeWriteCleanLog: Current swap logfile not replaced.\n");
+ safeunlink(tmp_filename, 0);
+ return 0;
+ }
if (file_write_unlock(swaplog_fd, swaplog_lock) != DISK_OK) {
debug(20, 0, "storeWriteCleanLog: Failed to unlock swaplog!\n");
debug(20, 0, "storeWriteCleanLog: Current swap logfile not replaced.\n");
debug(20, 1, "Store logging disabled\n");
}
}
+
+/*
+ * Check if its okay to remove the memory data for this object, but
+ * leave the StoreEntry around. Designed to be called from
+ * storeUnlockObject() and storeSwapOutHandle().
+ */
+static int storeCheckPurgeMem(e)
+ StoreEntry *e;
+{
+ if (storeEntryLocked(e))
+ return 0;
+ if (e->store_status != STORE_OK)
+ return 0;
+ if (store_hotobj_high)
+ return 0;
+ return 1;
+}
-
-/* $Id: tools.cc,v 1.42 1996/05/01 22:36:41 wessels Exp $ */
+/*
+ * $Id: tools.cc,v 1.43 1996/07/09 03:41:45 wessels Exp $
+ *
+ * DEBUG: section 21 Misc Functions
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
/*
- * DEBUG: Section 21 tools
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
time_t squid_curtime;
struct timeval current_time;
-extern void serverConnectionsClose _PARAMS((void));
-
#define DEAD_MSG "\
The Squid Cache (version %s) died.\n\
\n\
{
#if HAVE_MALLINFO
struct mallinfo mp;
-
+ int t;
if (!do_mallinfo)
return;
-
mp = mallinfo();
-
- fprintf(f, "Malloc Instrumentation via mallinfo(): \n");
- fprintf(f, " total space in arena %d\n", mp.arena);
- fprintf(f, " number of ordinary blocks %d\n", mp.ordblks);
- fprintf(f, " number of small blocks %d\n", mp.smblks);
- fprintf(f, " number of holding blocks %d\n", mp.hblks);
- fprintf(f, " space in holding block headers %d\n", mp.hblkhd);
- fprintf(f, " space in small blocks in use %d\n", mp.usmblks);
- fprintf(f, " space in free blocks %d\n", mp.fsmblks);
- fprintf(f, " space in ordinary blocks in use %d\n", mp.uordblks);
- fprintf(f, " space in free ordinary blocks %d\n", mp.fordblks);
- fprintf(f, " cost of enabling keep option %d\n", mp.keepcost);
+ fprintf(f, "Memory usage for %s via mallinfo():\n", appname);
+ fprintf(f, "\ttotal space in arena: %6d KB\n",
+ mp.arena >> 10);
+ fprintf(f, "\tOrdinary blocks: %6d KB %6d blks\n",
+ mp.uordblks >> 10, mp.ordblks);
+ fprintf(f, "\tSmall blocks: %6d KB %6d blks\n",
+ mp.usmblks >> 10, mp.smblks);
+ fprintf(f, "\tHolding blocks: %6d KB %6d blks\n",
+ mp.hblkhd >> 10, mp.hblks);
+ fprintf(f, "\tFree Small blocks: %6d KB\n",
+ mp.fsmblks >> 10);
+ fprintf(f, "\tFree Ordinary blocks: %6d KB\n",
+ mp.fordblks >> 10);
+ t = mp.uordblks + mp.usmblks + mp.hblkhd;
+ fprintf(f, "\tTotal in use: %6d KB %d%%\n",
+ t >> 10, percent(t, mp.arena));
+ t = mp.fsmblks + mp.fordblks;
+ fprintf(f, "\tTotal free: %6d KB %d%%\n",
+ t >> 10, percent(t, mp.arena));
+#ifdef WE_DONT_USE_KEEP
+ fprintf(f, "\tKeep option: %6d KB\n",
+ mp.keepcost >> 10);
+#endif
#if HAVE_EXT_MALLINFO
- fprintf(f, " max size of small blocks %d\n", mp.mxfast);
- fprintf(f, " number of small blocks in a holding block %d\n",
+ fprintf(f, "\tmax size of small blocks:\t%d\n",
+ mp.mxfast);
+ fprintf(f, "\tnumber of small blocks in a holding block:\t%d\n",
mp.nlblks);
- fprintf(f, " small block rounding factor %d\n", mp.grain);
- fprintf(f, " space (including overhead) allocated in ord. blks %d\n",
+ fprintf(f, "\tsmall block rounding factor:\t%d\n",
+ mp.grain);
+ fprintf(f, "\tspace (including overhead) allocated in ord. blks:\t%d\n",
mp.uordbytes);
- fprintf(f, " number of ordinary blocks allocated %d\n",
+ fprintf(f, "\tnumber of ordinary blocks allocated:\t%d\n",
mp.allocated);
- fprintf(f, " bytes used in maintaining the free tree %d\n",
+ fprintf(f, "\tbytes used in maintaining the free tree:\t%d\n",
mp.treeoverhead);
#endif /* HAVE_EXT_MALLINFO */
-
#if PRINT_MMAP
mallocmap();
#endif /* PRINT_MMAP */
#endif /* HAVE_MALLINFO */
}
+
static int PrintRusage(f, lf)
void (*f) ();
FILE *lf;
{
-#if HAVE_RUSAGE && defined(RUSAGE_SELF)
+#if HAVE_GETRUSAGE && defined(RUSAGE_SELF)
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
- fprintf(lf, "CPU Usage: user %d sys %d\nMemory Usage: rss %d KB\n",
- rusage.ru_utime.tv_sec, rusage.ru_stime.tv_sec,
- rusage.ru_maxrss * getpagesize() / 1000);
- fprintf(lf, "Page faults with physical i/o: %d\n",
+ fprintf(lf, "CPU Usage: user %d sys %d\n",
+ (int) rusage.ru_utime.tv_sec, (int) rusage.ru_stime.tv_sec);
+ fprintf(lf, "Memory Usage: rss %ld KB\n",
+ rusage.ru_maxrss * getpagesize() >> 10);
+ fprintf(lf, "Page faults with physical i/o: %ld\n",
rusage.ru_majflt);
#endif
dumpMallocStats(lf);
fprintf(debug_log, "FATAL: Received bus error...dying.\n");
else
fprintf(debug_log, "FATAL: Received signal %d...dying.\n", sig);
+#if !HAVE_SIGACTION
signal(SIGSEGV, SIG_DFL);
signal(SIGBUS, SIG_DFL);
signal(sig, SIG_DFL);
+#endif
storeWriteCleanLog();
PrintRusage(NULL, debug_log);
print_warranty();
}
-void rotate_logs(sig)
+void sigusr2_handle(sig)
int sig;
{
- debug(21, 1, "rotate_logs: SIGUSR1 received.\n");
-
- storeWriteCleanLog();
- storeRotateLog();
- neighbors_rotate_log();
- stat_rotate_log();
- _db_rotate_log();
-#if RESET_SIGNAL_HANDLER
- signal(sig, rotate_logs);
+ static int state = 0;
+ debug(21, 1, "sigusr2_handle: SIGUSR2 received.\n");
+ if (state == 0) {
+ _db_init(getCacheLogFile(), "ALL,10");
+ state = 1;
+ } else {
+ _db_init(getCacheLogFile(), getDebugOptions());
+ state = 0;
+ }
+#if !HAVE_SIGACTION
+ signal(sig, sigusr2_handle); /* reinstall */
#endif
}
+void setSocketShutdownLifetimes()
+{
+ FD_ENTRY *f = NULL;
+ int lft = getShutdownLifetime();
+ int cur;
+ int i;
+ for (i = fdstat_biggest_fd(); i >= 0; i--) {
+ f = &fd_table[i];
+ if (!f->read_handler && !f->write_handler && !f->except_handler)
+ continue;
+ if (fdstatGetType(i) != FD_SOCKET)
+ continue;
+ cur = comm_get_fd_lifetime(i);
+ if (cur > 0 && (cur - squid_curtime) <= lft)
+ continue;
+ comm_set_fd_lifetime(i, lft);
+ }
+}
+
void normal_shutdown()
{
debug(21, 1, "Shutting down...\n");
if (getPidFilename()) {
- get_suid();
+ enter_suid();
safeunlink(getPidFilename(), 0);
- check_suid();
+ leave_suid();
}
storeWriteCleanLog();
PrintRusage(NULL, debug_log);
version_string);
exit(0);
}
-void shut_down(sig)
- int sig;
-{
- int i;
- int lft = getShutdownLifetime();
- FD_ENTRY *f;
- debug(21, 1, "Preparing for shutdown after %d connections\n",
- ntcpconn + nudpconn);
- serverConnectionsClose();
- ipcacheShutdownServers();
- ftpServerClose();
- for (i = fdstat_biggest_fd(); i >= 0; i--) {
- f = &fd_table[i];
- if (f->read_handler || f->write_handler || f->except_handler)
- if (fdstatGetType(i) == Socket)
- comm_set_fd_lifetime(i, lft);
- }
- shutdown_pending = 1;
- /* reinstall signal handler? */
-}
void fatal_common(message)
char *message;
abort();
}
-
-int getHeapSize()
-{
-#if HAVE_MALLINFO
- struct mallinfo mp;
-
- mp = mallinfo();
-
- return (mp.arena);
-#else
- return (0);
-#endif
-}
-
void sig_child(sig)
int sig;
{
+#ifdef _SQUID_NEXT_
+ union wait status;
+#else
int status;
- int pid;
-
- if ((pid = waitpid(-1, &status, WNOHANG)) > 0)
- debug(21, 3, "sig_child: Ate pid %d\n", pid);
-
-#if RESET_SIGNAL_HANDLER
- signal(sig, sig_child);
#endif
-}
+ int pid;
-#ifdef OLD_CODE
-/*
- * getMaxFD - returns the file descriptor table size
- */
-int getMaxFD()
-{
- static int i = -1;
-
- if (i == -1) {
-#if HAVE_SYSCONF && defined(_SC_OPEN_MAX)
- i = sysconf(_SC_OPEN_MAX); /* prefered method */
-#elif HAVE_GETDTABLESIZE
- i = getdtablesize(); /* the BSD way */
-#elif defined(OPEN_MAX)
- i = OPEN_MAX;
-#elif defined(NOFILE)
- i = NOFILE;
-#elif defined(_NFILE)
- i = _NFILE;
+ do {
+#ifdef _SQUID_NEXT_
+ pid = wait3(&status, WNOHANG, NULL);
#else
- i = 64; /* 64 is a safe default */
+ pid = waitpid(-1, &status, WNOHANG);
#endif
- debug(21, 10, "getMaxFD set MaxFD at %d\n", i);
- }
- return (i);
-}
+ debug(21, 3, "sig_child: Ate pid %d\n", pid);
+#if HAVE_SIGACTION
+ } while (pid > 0);
#else
-int getMaxFD()
-{
- return FD_SETSIZE;
-}
+ } while (pid > 0 || (pid < 0 && errno == EINTR));
+ signal(sig, sig_child);
#endif
+}
char *getMyHostname()
{
xstrerror());
return NULL;
} else {
- if ((h = ipcache_gethostbyname(host)) != NULL) {
+ if ((h = ipcache_gethostbyname(host, IP_BLOCKING_LOOKUP)) != NULL) {
/* DNS lookup successful */
/* use the official name from DNS lookup */
strcpy(host, h->h_name);
return (err);
}
-/*
- * Daemonize a process according to guidlines in "Advanced Programming
- * For The UNIX Environment", W.R. Stevens ( Addison Wesley, 1992) - Ch. 13
+/* leave a privilegied section. (Give up any privilegies)
+ * Routines that need privilegies can rap themselves in enter_suid()
+ * and leave_suid()
+ * To give upp all posibilites to gain privilegies use no_suid()
*/
-int daemonize()
-{
- int n_openf, i;
- pid_t pid;
- if ((pid = fork()) < 0)
- return -1;
- else if (pid != 0)
- exit(0);
- /* Child continues */
- setsid(); /* Become session leader */
- n_openf = getMaxFD(); /* Close any inherited files */
- for (i = 0; i < n_openf; i++)
- close(i);
- umask(0); /* Clear file mode creation mask */
- return 0;
-}
-
-void check_suid()
+void leave_suid()
{
struct passwd *pwd = NULL;
struct group *grp = NULL;
+ debug(21, 3, "leave_suid: PID %d called\n", getpid());
if (geteuid() != 0)
return;
/* Started as a root, check suid option */
} else {
setgid(pwd->pw_gid);
}
+ debug(21, 3, "leave_suid: PID %d giving up root, becoming '%s'\n",
+ getpid(), pwd->pw_name);
#if HAVE_SETRESUID
setresuid(pwd->pw_uid, pwd->pw_uid, 0);
#elif HAVE_SETEUID
#endif
}
-void get_suid()
+/* Enter a privilegied section */
+void enter_suid()
{
+ debug(21, 3, "enter_suid: PID %d taking root priveleges\n", getpid());
#if HAVE_SETRESUID
setresuid(-1, 0, -1);
#else
#endif
}
+/* Give up the posibility to gain privilegies.
+ * this should be used before starting a sub process
+ */
void no_suid()
{
uid_t uid;
- check_suid();
+ leave_suid();
uid = geteuid();
+ debug(21, 3, "leave_suid: PID %d giving up root priveleges forever\n", getpid());
#if HAVE_SETRESUID
setresuid(uid, uid, uid);
#else
if ((f = getPidFilename()) == NULL)
return;
- if ((pid_fp = fopen(f, "w")) == NULL) {
+ enter_suid();
+ pid_fp = fopen(f, "w");
+ leave_suid();
+ if (pid_fp != NULL) {
+ fprintf(pid_fp, "%d\n", (int) getpid());
+ fclose(pid_fp);
+ } else {
debug(21, 0, "WARNING: Could not write pid file\n");
debug(21, 0, " %s: %s\n", f, xstrerror());
- return;
}
- fprintf(pid_fp, "%d\n", (int) getpid());
- fclose(pid_fp);
}
debug(21, 0, "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
} else {
rl.rlim_cur = FD_SETSIZE;
+ if (rl.rlim_cur > rl.rlim_max)
+ rl.rlim_cur = rl.rlim_max;
if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
sprintf(tmp_error_buf, "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
fatal_dump(tmp_error_buf);
debug(21, 0, "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
} else {
rl.rlim_cur = FD_SETSIZE;
+ if (rl.rlim_cur > rl.rlim_max)
+ rl.rlim_cur = rl.rlim_max;
if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
sprintf(tmp_error_buf, "setrlimit: RLIMIT_OFILE: %s", xstrerror());
fatal_dump(tmp_error_buf);
#endif
#else /* HAVE_SETRLIMIT */
debug(21, 1, "setMaxFD: Cannot increase: setrlimit() not supported on this system");
-#endif
+#endif /* HAVE_SETRLIMIT */
+
+#if HAVE_SETRLIMIT && defined(RLIMIT_DATA)
+ if (getrlimit(RLIMIT_DATA, &rl) < 0) {
+ debug(21, 0, "getrlimit: RLIMIT_DATA: %s", xstrerror());
+ } else {
+ rl.rlim_cur = rl.rlim_max; /* set it to the max */
+ if (setrlimit(RLIMIT_DATA, &rl) < 0) {
+ sprintf(tmp_error_buf, "setrlimit: RLIMIT_DATA: %s", xstrerror());
+ fatal_dump(tmp_error_buf);
+ }
+ }
+#endif /* RLIMIT_DATA */
}
time_t getCurrentTime()
{
+#if defined(_SQUID_MOTOROLA_)
+ gettimeofday(¤t_time);
+#else
gettimeofday(¤t_time, NULL);
- return squid_curtime = current_time.tv_sec;
-}
-
-
-void reconfigure(sig)
- int sig;
-{
- int i;
- int lft = getShutdownLifetime();
- FD_ENTRY *f;
- debug(21, 1, "reconfigure: SIGHUP received.\n");
- serverConnectionsClose();
- ipcacheShutdownServers();
- ftpServerClose();
- reread_pending = 1;
- for (i = fdstat_biggest_fd(); i >= 0; i--) {
- f = &fd_table[i];
- if (f->read_handler || f->write_handler || f->except_handler)
- if (fdstatGetType(i) == Socket)
- comm_set_fd_lifetime(i, lft);
- }
-#if RESET_SIGNAL_HANDLER
- signal(sig, reconfigure);
#endif
+ return squid_curtime = current_time.tv_sec;
}
int tvSubMsec(t1, t2)
return (t2.tv_sec - t1.tv_sec) * 1000 +
(t2.tv_usec - t1.tv_usec) / 1000;
}
+
+int percent(a, b)
+ int a;
+ int b;
+{
+ return b ? ((int) (100.0 * a / b + 0.5)) : 0;
+}
+
+void squid_signal(sig, func, flags)
+ int sig;
+ void (*func) ();
+ int flags;
+{
+#if HAVE_SIGACTION
+ struct sigaction sa;
+ sa.sa_handler = func;
+ sa.sa_flags = flags;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(sig, &sa, NULL) < 0)
+ debug(1, 0, "sigaction: sig=%d func=%p: %s\n", sig, func, xstrerror());
+#else
+ (void) signal(sig, func);
+#endif
+}
/*
- * $Id: tunnel.cc,v 1.2 1996/05/03 22:56:31 wessels Exp $
+ * $Id: tunnel.cc,v 1.3 1996/07/09 03:41:39 wessels Exp $
*
- * DEBUG: Section 26 ssl
+ * DEBUG: section 26 Secure Sockets Layer Proxy
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
*/
-#include "squid.h"
-#define SSL_BUFSIZ (1<<14)
+#include "squid.h"
typedef struct {
char *url;
static void sslWriteServer _PARAMS((int fd, SslStateData * sslState));
static void sslWriteClient _PARAMS((int fd, SslStateData * sslState));
static void sslConnected _PARAMS((int fd, SslStateData * sslState));
+static int sslConnect _PARAMS((int fd, struct hostent *, SslStateData *));
static void sslConnInProgress _PARAMS((int fd, SslStateData * sslState));
+static void sslErrorComplete _PARAMS((int, char *, int, int, void *));
+static void sslClose _PARAMS((SslStateData * sslState));
+static int sslClientClosed _PARAMS((int fd, SslStateData * sslState));
+
+static void sslClose(sslState)
+ SslStateData *sslState;
+{
+ if (sslState->client.fd > -1) {
+ /* remove the "unexpected" client close handler */
+ comm_remove_close_handler(sslState->client.fd,
+ (PF) sslClientClosed,
+ (void *) sslState);
+ comm_close(sslState->client.fd);
+ sslState->client.fd = -1;
+ }
+ if (sslState->server.fd > -1) {
+ comm_close(sslState->server.fd);
+ }
+}
+
+/* This is called only if the client connect closes unexpectedly,
+ * ie from icpDetectClientClose() */
+static int sslClientClosed(fd, sslState)
+ int fd;
+ SslStateData *sslState;
+{
+ debug(26, 3, "sslClientClosed: FD %d\n", fd);
+ /* we have been called from comm_close for the client side, so
+ * just need to clean up the server side */
+ comm_close(sslState->server.fd);
+ return 0;
+}
static int sslStateFree(fd, sslState)
int fd;
safe_free(sslState->server.buf);
safe_free(sslState->client.buf);
xfree(sslState->url);
+ requestUnlink(sslState->request);
memset(sslState, '\0', sizeof(SslStateData));
safe_free(sslState);
return 0;
{
debug(26, 4, "sslLifeTimeExpire: FD %d: URL '%s'>\n",
fd, sslState->url);
- comm_close(sslState->client.fd); /* close client first */
- comm_close(sslState->server.fd);
+ sslClose(sslState);
}
/* Read from server side and queue it for writing to the client */
SslStateData *sslState;
{
int len;
- len = read(sslState->server.fd, sslState->server.buf, 4096);
+ len = read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF);
debug(26, 5, "sslReadServer FD %d, read %d bytes\n", fd, len);
if (len < 0) {
debug(26, 1, "sslReadServer: FD %d: read failure: %s\n",
(void *) sslState,
sslState->timeout);
} else {
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
}
} else if (len == 0) {
/* Connection closed; retrieval done. */
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
} else {
sslState->server.offset = 0;
sslState->server.len = len;
SslStateData *sslState;
{
int len;
- len = read(sslState->client.fd, sslState->client.buf, 4096);
+ len = read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF);
debug(26, 5, "sslReadClient FD %d, read %d bytes\n",
sslState->client.fd, len);
if (len < 0) {
(void *) sslState,
sslState->timeout);
} else {
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
}
} else if (len == 0) {
/* Connection closed; retrieval done. */
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
} else {
sslState->client.offset = 0;
sslState->client.len = len;
if (len < 0) {
debug(26, 2, "sslWriteServer: FD %d: write failure: %s.\n",
sslState->server.fd, xstrerror());
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
return;
}
if ((sslState->client.offset += len) >= sslState->client.len) {
if (len < 0) {
debug(26, 2, "sslWriteClient: FD %d: write failure: %s.\n",
sslState->client.fd, xstrerror());
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
return;
}
if (sslState->size_ptr)
int fd;
SslStateData *sslState;
{
- if (fd != sslState->server.fd)
- fatal_dump("sslReadTimeout: FD mismatch!\n");
debug(26, 3, "sslReadTimeout: FD %d\n", fd);
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ sslClose(sslState);
}
static void sslConnected(fd, sslState)
COMM_SELECT_WRITE,
(PF) sslWriteClient,
(void *) sslState);
- comm_set_fd_lifetime(fd, -1); /* disable lifetime */
+ comm_set_fd_lifetime(fd, 86400); /* extend lifetime */
comm_set_select_handler_plus_timeout(sslState->server.fd,
COMM_SELECT_TIMEOUT,
(PF) sslReadTimeout,
(void *) sslState);
}
+static void sslErrorComplete(fd, buf, size, errflag, sslState)
+ int fd;
+ char *buf;
+ int size;
+ int errflag;
+ void *sslState;
+{
+ safe_free(buf);
+ sslClose(sslState);
+}
+
static void sslConnInProgress(fd, sslState)
int fd;
SslStateData *sslState;
{
request_t *req = sslState->request;
+ char *buf = NULL;
debug(26, 5, "sslConnInProgress: FD %d sslState=%p\n", fd, sslState);
if (comm_connect(fd, req->host, req->port) != COMM_OK) {
- debug(26, 5, "sslConnInProgress: FD %d: %s", fd, xstrerror());
+ debug(26, 5, "sslConnInProgress: FD %d: %s\n", fd, xstrerror());
switch (errno) {
#if EINPROGRESS != EALREADY
case EINPROGRESS:
(void *) sslState);
return;
default:
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ buf = squid_error_url(sslState->url,
+ METHOD_CONNECT,
+ ERR_CONNECT_FAIL,
+ NULL,
+ 500,
+ xstrerror());
+ comm_write(sslState->client.fd,
+ xstrdup(buf),
+ strlen(buf),
+ 30,
+ sslErrorComplete,
+ sslState);
return;
}
}
return;
}
-
-int sslStart(fd, url, request, mime_hdr, size_ptr)
+static int sslConnect(fd, hp, sslState)
int fd;
- char *url;
- request_t *request;
- char *mime_hdr;
- int *size_ptr;
+ struct hostent *hp;
+ SslStateData *sslState;
{
- /* Create state structure. */
- int sock, status;
- SslStateData *sslState = NULL;
-
- debug(26, 3, "sslStart: '%s %s'\n",
- RequestMethodStr[request->method], url);
-
- /* Create socket. */
- sock = comm_open(COMM_NONBLOCKING, 0, 0, url);
- if (sock == COMM_ERROR) {
- debug(26, 4, "sslStart: Failed because we're out of sockets.\n");
- squid_error_url(url,
- request->method,
- ERR_NO_FDS,
- fd_table[fd].ipaddr,
- 500,
- xstrerror());
- return COMM_ERROR;
- }
- sslState = (SslStateData *) xcalloc(1, sizeof(SslStateData));
- sslState->url = xstrdup(url);
- sslState->request = request;
- sslState->mime_hdr = mime_hdr;
- sslState->timeout = getReadTimeout();
- sslState->size_ptr = size_ptr;
- sslState->client.fd = fd;
- sslState->server.fd = sock;
- sslState->server.buf = xmalloc(SSL_BUFSIZ);
- sslState->client.buf = xmalloc(SSL_BUFSIZ);
- comm_set_select_handler(sslState->server.fd,
- COMM_SELECT_CLOSE,
- (PF) sslStateFree,
- (void *) sslState);
-
- /* check if IP is already in cache. It must be.
- * It should be done before this route is called.
- * Otherwise, we cannot check return code for ssl. */
- if (!ipcache_gethostbyname(request->host)) {
- debug(26, 4, "sslstart: Called without IP entry in ipcache. OR lookup failed.\n");
- squid_error_url(url,
+ request_t *request = sslState->request;
+ int status;
+ char *buf = NULL;
+ if (!ipcache_gethostbyname(request->host, 0)) {
+ debug(26, 4, "sslConnect: Unknown host: %s\n", request->host);
+ buf = squid_error_url(sslState->url,
request->method,
ERR_DNS_FAIL,
fd_table[fd].ipaddr,
500,
dns_error_message);
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ comm_write(sslState->client.fd,
+ xstrdup(buf),
+ strlen(buf),
+ 30,
+ sslErrorComplete,
+ (void *) sslState);
return COMM_ERROR;
}
- debug(26, 5, "sslStart: client=%d server=%d\n",
+ debug(26, 5, "sslConnect: client=%d server=%d\n",
sslState->client.fd,
sslState->server.fd);
/* Install lifetime handler */
(PF) sslLifetimeExpire,
(void *) sslState);
/* Open connection. */
- if ((status = comm_connect(sock, request->host, request->port))) {
+ if ((status = comm_connect(fd, request->host, request->port))) {
if (status != EINPROGRESS) {
- squid_error_url(url,
+ buf = squid_error_url(sslState->url,
request->method,
ERR_CONNECT_FAIL,
fd_table[fd].ipaddr,
500,
xstrerror());
- comm_close(sslState->client.fd);
- comm_close(sslState->server.fd);
+ comm_write(sslState->client.fd,
+ xstrdup(buf),
+ strlen(buf),
+ 30,
+ sslErrorComplete,
+ (void *) sslState);
return COMM_ERROR;
} else {
- debug(26, 5, "sslStart: conn %d EINPROGRESS\n", sock);
+ debug(26, 5, "sslConnect: conn %d EINPROGRESS\n", fd);
/* The connection is in progress, install ssl handler */
comm_set_select_handler(sslState->server.fd,
COMM_SELECT_WRITE,
return COMM_OK;
}
}
- /* We got immediately connected. (can this happen?) */
sslConnected(sslState->server.fd, sslState);
return COMM_OK;
}
+
+int sslStart(fd, url, request, mime_hdr, size_ptr)
+ int fd;
+ char *url;
+ request_t *request;
+ char *mime_hdr;
+ int *size_ptr;
+{
+ /* Create state structure. */
+ SslStateData *sslState = NULL;
+ int sock;
+ char *buf = NULL;
+
+ debug(26, 3, "sslStart: '%s %s'\n",
+ RequestMethodStr[request->method], url);
+
+ /* Create socket. */
+ sock = comm_open(COMM_NONBLOCKING, getTcpOutgoingAddr(), 0, url);
+ if (sock == COMM_ERROR) {
+ debug(26, 4, "sslStart: Failed because we're out of sockets.\n");
+ buf = squid_error_url(url,
+ request->method,
+ ERR_NO_FDS,
+ fd_table[fd].ipaddr,
+ 500,
+ xstrerror());
+ comm_write(sslState->client.fd,
+ xstrdup(buf),
+ strlen(buf),
+ 30,
+ sslErrorComplete,
+ (void *) sslState);
+ return COMM_ERROR;
+ }
+ sslState = xcalloc(1, sizeof(SslStateData));
+ sslState->url = xstrdup(url);
+ sslState->request = requestLink(request);
+ sslState->mime_hdr = mime_hdr;
+ sslState->timeout = getReadTimeout();
+ sslState->size_ptr = size_ptr;
+ sslState->client.fd = fd;
+ sslState->server.fd = sock;
+ sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
+ sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
+ comm_add_close_handler(sslState->server.fd,
+ (PF) sslStateFree,
+ (void *) sslState);
+ comm_add_close_handler(sslState->client.fd,
+ (PF) sslClientClosed,
+ (void *) sslState);
+ ipcache_nbgethostbyname(request->host,
+ sslState->server.fd,
+ (IPH) sslConnect,
+ sslState);
+ return COMM_OK;
+}
-/* $Id: url.cc,v 1.21 1996/05/03 22:56:33 wessels Exp $ */
-
-/*
- * DEBUG: Section 23 url
+/*
+ * $Id: url.cc,v 1.22 1996/07/09 03:41:46 wessels Exp $
+ *
+ * DEBUG: section 23 URL Parsing
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
*/
#include "squid.h"
"NONE",
"GET",
"POST",
+ "PUT",
"HEAD",
"CONNECT"
};
url = allocate ? (char *) xstrdup(org_url) : org_url;
- if (strlen(url) < 3 || !strchr(url, '%'))
+ if ((int) strlen(url) < 3 || !strchr(url, '%'))
return url;
for (s = t = url; *(s + 2); s++) {
return METHOD_GET;
} else if (strcasecmp(s, "POST") == 0) {
return METHOD_POST;
+ } else if (strcasecmp(s, "PUT") == 0) {
+ return METHOD_PUT;
} else if (strcasecmp(s, "HEAD") == 0) {
return METHOD_HEAD;
} else if (strcasecmp(s, "CONNECT") == 0) {
*t = 0;
strcpy(host, t + 1);
}
- if ((t = strrchr(host, ':')) && *(t + 1) != '\0') {
- *t = '\0';
- port = atoi(t + 1);
+ if ((t = strrchr(host, ':'))) {
+ *t++ = '\0';
+ if (*t != '\0')
+ port = atoi(t);
}
}
for (t = host; *t; t++)
debug(23, 0, "urlParse: Invalid port == 0\n");
return NULL;
}
- request = (request_t *) xcalloc(1, sizeof(request_t));
+ request = get_free_request_t();
request->method = method;
request->protocol = protocol;
strncpy(request->host, host, SQUIDHOSTNAMELEN);
}
return buf;
}
+
+request_t *requestLink(request)
+ request_t *request;
+{
+ request->link_count++;
+ return request;
+}
+
+void requestUnlink(request)
+ request_t *request;
+{
+ if (request == NULL)
+ return;
+ request->link_count--;
+ if (request->link_count == 0)
+ put_free_request_t(request);
+}
+
+int matchDomainName(domain, host)
+ char *domain;
+ char *host;
+{
+ int offset;
+ if ((offset = strlen(host) - strlen(domain)) < 0)
+ return 0; /* host too short */
+ if (strcasecmp(domain, host + offset) != 0)
+ return 0; /* no match at all */
+ if (*domain == '.')
+ return 1;
+ if (*(host + offset - 1) == '.')
+ return 1;
+ if (offset == 0)
+ return 1;
+ return 0;
+}
-/* $Id: wais.cc,v 1.30 1996/05/03 22:56:34 wessels Exp $ */
+/*
+ * $Id: wais.cc,v 1.31 1996/07/09 03:41:47 wessels Exp $
+ *
+ * DEBUG: section 24 WAIS Relay
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Internet Object Cache http://www.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
/*
- * DEBUG: Section 24 wais
+ * Copyright (c) 1994, 1995. All rights reserved.
+ *
+ * The Harvest software was developed by the Internet Research Task
+ * Force Research Group on Resource Discovery (IRTF-RD):
+ *
+ * Mic Bowman of Transarc Corporation.
+ * Peter Danzig of the University of Southern California.
+ * Darren R. Hardy of the University of Colorado at Boulder.
+ * Udi Manber of the University of Arizona.
+ * Michael F. Schwartz of the University of Colorado at Boulder.
+ * Duane Wessels of the University of Colorado at Boulder.
+ *
+ * This copyright notice applies to software in the Harvest
+ * ``src/'' directory only. Users should consult the individual
+ * copyright notices in the ``components/'' subdirectories for
+ * copyright information about other software bundled with the
+ * Harvest source code distribution.
+ *
+ * TERMS OF USE
+ *
+ * The Harvest software may be used and re-distributed without
+ * charge, provided that the software origin and research team are
+ * cited in any use of the system. Most commonly this is
+ * accomplished by including a link to the Harvest Home Page
+ * (http://harvest.cs.colorado.edu/) from the query page of any
+ * Broker you deploy, as well as in the query result pages. These
+ * links are generated automatically by the standard Broker
+ * software distribution.
+ *
+ * The Harvest software is provided ``as is'', without express or
+ * implied warranty, and with no support nor obligation to assist
+ * in its use, correction, modification or enhancement. We assume
+ * no liability with respect to the infringement of copyrights,
+ * trade secrets, or any patents, and are not responsible for
+ * consequential damages. Proper use of the Harvest software is
+ * entirely the responsibility of the user.
+ *
+ * DERIVATIVE WORKS
+ *
+ * Users may make derivative works from the Harvest software, subject
+ * to the following constraints:
+ *
+ * - You must include the above copyright notice and these
+ * accompanying paragraphs in all forms of derivative works,
+ * and any documentation and other materials related to such
+ * distribution and use acknowledge that the software was
+ * developed at the above institutions.
+ *
+ * - You must notify IRTF-RD regarding your distribution of
+ * the derivative work.
+ *
+ * - You must clearly notify users that your are distributing
+ * a modified version and not the original Harvest software.
+ *
+ * - Any derivative product is also subject to these copyright
+ * and use restrictions.
+ *
+ * Note that the Harvest software is NOT in the public domain. We
+ * retain copyright, as specified above.
+ *
+ * HISTORY OF FREE SOFTWARE STATUS
+ *
+ * Originally we required sites to license the software in cases
+ * where they were going to build commercial products/services
+ * around Harvest. In June 1995 we changed this policy. We now
+ * allow people to use the core Harvest software (the code found in
+ * the Harvest ``src/'' directory) for free. We made this change
+ * in the interest of encouraging the widest possible deployment of
+ * the technology. The Harvest software is really a reference
+ * implementation of a set of protocols and formats, some of which
+ * we intend to standardize. We encourage commercial
+ * re-implementations of code complying to this set of standards.
*/
#include "squid.h"
#define WAIS_DELETE_GAP (64*1024)
-typedef struct _waisdata {
+typedef struct {
+ int fd;
StoreEntry *entry;
method_t method;
char *relayhost;
int relayport;
char *mime_hdr;
char request[MAX_URL];
-} WAISData;
+} WaisStateData;
+
+static int waisStateFree _PARAMS((int, WaisStateData *));
+static void waisReadReplyTimeout _PARAMS((int, WaisStateData *));
+static void waisLifetimeExpire _PARAMS((int, WaisStateData *));
+static void waisReadReply _PARAMS((int, WaisStateData *));
+static void waisSendComplete _PARAMS((int, char *, int, int, void *));
+static void waisSendRequest _PARAMS((int, WaisStateData *));
+static void waisConnInProgress _PARAMS((int, WaisStateData *));
+static int waisConnect _PARAMS((int, struct hostent *, WaisStateData *));
static int waisStateFree(fd, waisState)
int fd;
- WAISData *waisState;
+ WaisStateData *waisState;
{
if (waisState == NULL)
return 1;
+ storeUnlockObject(waisState->entry);
xfree(waisState);
return 0;
}
/* This will be called when timeout on read. */
-static void waisReadReplyTimeout(fd, data)
+static void waisReadReplyTimeout(fd, waisState)
int fd;
- WAISData *data;
+ WaisStateData *waisState;
{
StoreEntry *entry = NULL;
- entry = data->entry;
+ entry = waisState->entry;
debug(24, 4, "waisReadReplyTimeout: Timeout on %d\n url: %s\n", fd, entry->url);
squid_error_entry(entry, ERR_READ_TIMEOUT, NULL);
comm_set_select_handler(fd, COMM_SELECT_READ, 0, 0);
}
/* This will be called when socket lifetime is expired. */
-void waisLifetimeExpire(fd, data)
+static void waisLifetimeExpire(fd, waisState)
int fd;
- WAISData *data;
+ WaisStateData *waisState;
{
StoreEntry *entry = NULL;
- entry = data->entry;
+ entry = waisState->entry;
debug(24, 4, "waisLifeTimeExpire: FD %d: <URL:%s>\n", fd, entry->url);
squid_error_entry(entry, ERR_LIFETIME_EXP, NULL);
comm_set_select_handler(fd, COMM_SELECT_READ | COMM_SELECT_WRITE, 0, 0);
/* This will be called when data is ready to be read from fd. Read until
* error or connection closed. */
-void waisReadReply(fd, data)
+static void waisReadReply(fd, waisState)
int fd;
- WAISData *data;
+ WaisStateData *waisState;
{
static char buf[4096];
int len;
StoreEntry *entry = NULL;
- entry = data->entry;
+ entry = waisState->entry;
if (entry->flag & DELETE_BEHIND) {
if (storeClientWaiting(entry)) {
/* check if we want to defer reading */
comm_set_select_handler(fd,
COMM_SELECT_READ,
(PF) waisReadReply,
- (void *) data);
+ (void *) waisState);
/* don't install read handler while we're above the gap */
comm_set_select_handler_plus_timeout(fd,
COMM_SELECT_TIMEOUT,
/* reinstall handlers */
/* XXX This may loop forever */
comm_set_select_handler(fd, COMM_SELECT_READ,
- (PF) waisReadReply, (void *) data);
+ (PF) waisReadReply, (void *) waisState);
comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT,
- (PF) waisReadReplyTimeout, (void *) data, getReadTimeout());
+ (PF) waisReadReplyTimeout, (void *) waisState, getReadTimeout());
} else {
BIT_RESET(entry->flag, CACHABLE);
storeReleaseRequest(entry);
comm_set_select_handler(fd,
COMM_SELECT_READ,
(PF) waisReadReply,
- (void *) data);
+ (void *) waisState);
comm_set_select_handler_plus_timeout(fd,
COMM_SELECT_TIMEOUT,
(PF) waisReadReplyTimeout,
- (void *) data,
+ (void *) waisState,
getReadTimeout());
} else {
storeAppend(entry, buf, len);
comm_set_select_handler(fd,
COMM_SELECT_READ,
(PF) waisReadReply,
- (void *) data);
+ (void *) waisState);
comm_set_select_handler_plus_timeout(fd,
COMM_SELECT_TIMEOUT,
(PF) waisReadReplyTimeout,
- (void *) data,
+ (void *) waisState,
getReadTimeout());
}
}
/* This will be called when request write is complete. Schedule read of
* reply. */
-void waisSendComplete(fd, buf, size, errflag, data)
+static void waisSendComplete(fd, buf, size, errflag, data)
int fd;
char *buf;
int size;
int errflag;
- WAISData *data;
+ void *data;
{
StoreEntry *entry = NULL;
- entry = data->entry;
+ WaisStateData *waisState = data;
+ entry = waisState->entry;
debug(24, 5, "waisSendComplete - fd: %d size: %d errflag: %d\n",
fd, size, errflag);
if (errflag) {
comm_set_select_handler(fd,
COMM_SELECT_READ,
(PF) waisReadReply,
- (void *) data);
+ (void *) waisState);
comm_set_select_handler_plus_timeout(fd,
COMM_SELECT_TIMEOUT,
(PF) waisReadReplyTimeout,
- (void *) data,
+ (void *) waisState,
getReadTimeout());
}
safe_free(buf); /* Allocated by waisSendRequest. */
}
/* This will be called when connect completes. Write request. */
-void waisSendRequest(fd, data)
+static void waisSendRequest(fd, waisState)
int fd;
- WAISData *data;
+ WaisStateData *waisState;
{
- int len = strlen(data->request) + 4;
+ int len = strlen(waisState->request) + 4;
char *buf = NULL;
- char *Method = RequestMethodStr[data->method];
+ char *Method = RequestMethodStr[waisState->method];
debug(24, 5, "waisSendRequest - fd: %d\n", fd);
if (Method)
len += strlen(Method);
- if (data->mime_hdr)
- len += strlen(data->mime_hdr);
+ if (waisState->mime_hdr)
+ len += strlen(waisState->mime_hdr);
- buf = (char *) xcalloc(1, len + 1);
+ buf = xcalloc(1, len + 1);
- if (data->mime_hdr)
- sprintf(buf, "%s %s %s\r\n", Method, data->request,
- data->mime_hdr);
+ if (waisState->mime_hdr)
+ sprintf(buf, "%s %s %s\r\n", Method, waisState->request,
+ waisState->mime_hdr);
else
- sprintf(buf, "%s %s\r\n", Method, data->request);
+ sprintf(buf, "%s %s\r\n", Method, waisState->request);
debug(24, 6, "waisSendRequest - buf:%s\n", buf);
- icpWrite(fd,
+ comm_write(fd,
buf,
len,
30,
waisSendComplete,
- (void *) data);
- if (BIT_TEST(data->entry->flag, CACHABLE))
- storeSetPublicKey(data->entry); /* Make it public */
+ (void *) waisState);
+ if (BIT_TEST(waisState->entry->flag, CACHABLE))
+ storeSetPublicKey(waisState->entry); /* Make it public */
+}
+
+static void waisConnInProgress(fd, waisState)
+ int fd;
+ WaisStateData *waisState;
+{
+ StoreEntry *entry = waisState->entry;
+
+ debug(11, 5, "waisConnInProgress: FD %d waisState=%p\n", fd, waisState);
+
+ if (comm_connect(fd, waisState->relayhost, waisState->relayport) != COMM_OK) {
+ debug(11, 5, "waisConnInProgress: FD %d: %s\n", fd, xstrerror());
+ switch (errno) {
+ case EINPROGRESS:
+ case EALREADY:
+ /* schedule this handler again */
+ comm_set_select_handler(fd,
+ COMM_SELECT_WRITE,
+ (PF) waisConnInProgress,
+ (void *) waisState);
+ return;
+ default:
+ squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
+ comm_close(fd);
+ return;
+ }
+ }
+ /* Call the real write handler, now that we're fully connected */
+ comm_set_select_handler(fd, COMM_SELECT_WRITE,
+ (PF) waisSendRequest, (void *) waisState);
}
int waisStart(unusedfd, url, method, mime_hdr, entry)
char *mime_hdr;
StoreEntry *entry;
{
- /* Create state structure. */
- int sock, status;
- WAISData *data = NULL;
+ WaisStateData *waisState = NULL;
+ int fd;
- debug(24, 3, "waisStart: \"%s %s\"\n",
- RequestMethodStr[method], url);
+ debug(24, 3, "waisStart: \"%s %s\"\n", RequestMethodStr[method], url);
debug(24, 4, " header: %s\n", mime_hdr);
-
if (!getWaisRelayHost()) {
debug(24, 0, "waisStart: Failed because no relay host defined!\n");
squid_error_entry(entry, ERR_NO_RELAY, NULL);
return COMM_ERROR;
}
- /* Create socket. */
- sock = comm_open(COMM_NONBLOCKING, 0, 0, url);
- if (sock == COMM_ERROR) {
+ fd = comm_open(COMM_NONBLOCKING, getTcpOutgoingAddr(), 0, url);
+ if (fd == COMM_ERROR) {
debug(24, 4, "waisStart: Failed because we're out of sockets.\n");
squid_error_entry(entry, ERR_NO_FDS, xstrerror());
return COMM_ERROR;
}
- data = (WAISData *) xcalloc(1, sizeof(WAISData));
- data->entry = entry;
- data->method = method;
- data->relayhost = getWaisRelayHost();
- data->relayport = getWaisRelayPort();
- data->mime_hdr = mime_hdr;
- comm_set_select_handler(sock,
- COMM_SELECT_CLOSE,
+ waisState = xcalloc(1, sizeof(WaisStateData));
+ storeLockObject(waisState->entry = entry, NULL, NULL);
+ waisState->method = method;
+ waisState->relayhost = getWaisRelayHost();
+ waisState->relayport = getWaisRelayPort();
+ waisState->mime_hdr = mime_hdr;
+ waisState->fd = fd;
+ strncpy(waisState->request, url, MAX_URL);
+ comm_add_close_handler(waisState->fd,
(PF) waisStateFree,
- (void *) data);
+ (void *) waisState);
+ ipcache_nbgethostbyname(waisState->relayhost,
+ waisState->fd,
+ (IPH) waisConnect,
+ waisState);
+ return COMM_OK;
+}
- /* check if IP is already in cache. It must be.
- * It should be done before this route is called.
- * Otherwise, we cannot check return code for connect. */
- if (!ipcache_gethostbyname(data->relayhost)) {
- debug(24, 4, "waisstart: Called without IP entry in ipcache. OR lookup failed.\n");
- squid_error_entry(entry, ERR_DNS_FAIL, dns_error_message);
- comm_close(sock);
+
+static int waisConnect(fd, hp, waisState)
+ int fd;
+ struct hostent *hp;
+ WaisStateData *waisState;
+{
+ int status;
+ char *host = waisState->relayhost;
+ u_short port = waisState->relayport;
+ if (!ipcache_gethostbyname(waisState->relayhost, 0)) {
+ debug(24, 4, "waisstart: Unknown host: %s\n", waisState->relayhost);
+ squid_error_entry(waisState->entry, ERR_DNS_FAIL, dns_error_message);
+ comm_close(waisState->fd);
return COMM_ERROR;
}
/* Open connection. */
- if ((status = comm_connect(sock, data->relayhost, data->relayport))) {
+ if ((status = comm_connect(fd, host, port))) {
if (status != EINPROGRESS) {
- squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
- comm_close(sock);
+ squid_error_entry(waisState->entry, ERR_CONNECT_FAIL, xstrerror());
+ comm_close(fd);
return COMM_ERROR;
} else {
- debug(24, 5, "waisStart: FD %d EINPROGRESS\n", sock);
+ debug(24, 5, "waisStart: FD %d EINPROGRESS\n", fd);
+ comm_set_select_handler(fd,
+ COMM_SELECT_LIFETIME,
+ (PF) waisLifetimeExpire,
+ (void *) waisState);
+ comm_set_select_handler(fd,
+ COMM_SELECT_WRITE,
+ (PF) waisConnInProgress,
+ (void *) waisState);
+ return COMM_OK;
}
}
/* Install connection complete handler. */
- comm_set_select_handler(sock, COMM_SELECT_LIFETIME,
- (PF) waisLifetimeExpire, (void *) data);
- comm_set_select_handler(sock, COMM_SELECT_WRITE,
- (PF) waisSendRequest, (void *) data);
+ comm_set_select_handler(fd,
+ COMM_SELECT_LIFETIME,
+ (PF) waisLifetimeExpire,
+ (void *) waisState);
+ comm_set_select_handler(fd,
+ COMM_SELECT_WRITE,
+ (PF) waisSendRequest,
+ (void *) waisState);
return COMM_OK;
}