mod_unique_id.c revision 6865813dee5d3c1ebf12dd810368171792a0190a
830N/A/* ==================================================================== 830N/A * The Apache Software License, Version 1.1 830N/A * Copyright (c) 2000-2001 The Apache Software Foundation. All rights 830N/A * Redistribution and use in source and binary forms, with or without 830N/A * modification, are permitted provided that the following conditions 830N/A * 1. Redistributions of source code must retain the above copyright 830N/A * notice, this list of conditions and the following disclaimer. 830N/A * 2. Redistributions in binary form must reproduce the above copyright 830N/A * notice, this list of conditions and the following disclaimer in 830N/A * the documentation and/or other materials provided with the 830N/A * 3. The end-user documentation included with the redistribution, 830N/A * if any, must include the following acknowledgment: 1415N/A * "This product includes software developed by the 839N/A * Alternately, this acknowledgment may appear in the software itself, 839N/A * if and wherever such third-party acknowledgments normally appear. 830N/A * 4. The names "Apache" and "Apache Software Foundation" must 1300N/A * not be used to endorse or promote products derived from this 1258N/A * software without prior written permission. For written 830N/A * permission, please contact apache@apache.org. 830N/A * 5. Products derived from this software may not be called "Apache", 830N/A * nor may "Apache" appear in their name, without prior written 830N/A * permission of the Apache Software Foundation. 830N/A * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 830N/A * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 830N/A * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1244N/A * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 1244N/A * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 830N/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1244N/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 1244N/A * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 844N/A * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 844N/A * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 830N/A * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 830N/A * ==================================================================== 830N/A * This software consists of voluntary contributions made by many 830N/A * individuals on behalf of the Apache Software Foundation. For more 830N/A * information on the Apache Software Foundation, please see 830N/A * Portions of this software are based upon public domain software 830N/A * originally written at the National Center for Supercomputing Applications, 830N/A * University of Illinois, Urbana-Champaign. 902N/A * Original author: Dean Gaudet <dgaudet@arctic.org> 902N/A * UUencoding modified by: Alvaro Martinez Echevarria <alvaro@lander.es> 830N/A/* We are using thread_index (the index into the scoreboard), because we 830N/A * cannot guarantee the thread_id will be an integer. 830N/A * This code looks like it won't give a unique ID with the new thread logic. 830N/A * It will. The reason is, we don't increment the counter in a thread_safe 830N/A * manner. Because the thread_index is also in the unique ID now, this does 830N/A * not matter. In order for the id to not be unique, the same thread would 830N/A * have to get the same counter twice in the same second. 830N/A * We want an identifier which is unique across all hits, everywhere. 830N/A * "everywhere" includes multiple httpd instances on the same machine, or on 830N/A * multiple machines. Essentially "everywhere" should include all possible 902N/A * httpds across all servers at a particular "site". We make some assumptions 902N/A * that if the site has a cluster of machines then their time is relatively 902N/A * synchronized. We also assume that the first address returned by a 830N/A * gethostbyname (gethostname()) is unique across all the machines at the 830N/A * We also further assume that pids fit in 32-bits. If something uses more 830N/A * than 32-bits, the fix is trivial, but it requires the unrolled uuencoding 830N/A * loop to be extended. * A similar fix is needed to support multithreaded 830N/A * Together, the in_addr and pid are assumed to absolutely uniquely identify 830N/A * this one child from all other currently running children on all servers 830N/A * (including this physical server if it is running multiple httpds) from each 830N/A * The stamp and counter are used to distinguish all hits for a particular 830N/A * (in_addr,pid) pair. The stamp is updated using r->request_time, 830N/A * saving cpu cycles. The counter is never reset, and is used to permit up to 830N/A * 64k requests in a single second by a single child. 830N/A * The 112-bits of unique_id_rec are encoded using the alphabet 830N/A * [A-Za-z0-9@-], resulting in 19 bytes of printable characters. That is then 830N/A * stuffed into the environment variable UNIQUE_ID so that it is available to 830N/A * other modules. The alphabet choice differs from normal base64 encoding 830N/A * [A-Za-z0-9+/] because + and / are special characters in URLs and we want to 990N/A * make it easy to use UNIQUE_ID in URLs. 990N/A * Note that UNIQUE_ID should be considered an opaque token by other 990N/A * applications. No attempt should be made to dissect its internal components. 990N/A * It is an abstraction that may change in the future as the needs of this 990N/A * It is highly desirable that identifiers exist for "eternity". But future 990N/A * needs (such as much faster webservers, moving to 64-bit pids, or moving to a 990N/A * multithreaded server) may dictate a need to change the contents of 990N/A * unique_id_rec. Such a future implementation should ensure that the first 990N/A * field is still a time_t stamp. By doing that, it is possible for a site to 990N/A * have a "flag second" in which they stop all of their old-format servers, 990N/A * wait one entire second, and then start all of their new-servers. This 990N/A * procedure will ensure that the new space of identifiers is completely unique 990N/A * from the old space. (Since the first four unencoded bytes always differ.) 990N/A * Sun Jun 7 05:43:49 CEST 1998 -- Alvaro 830N/A * 1) The UUencoding prodecure is now done in a general way, avoiding the problems 830N/A * with sizes and paddings that can arise depending on the architecture. Now the 830N/A * offsets and sizes of the elements of the unique_id_rec structure are calculated 830N/A * in unique_id_global_init; and then used to duplicate the structure without the 830N/A * paddings that might exist. The multithreaded server fix should be now very easy: 830N/A * just add a new "tid" field to the unique_id_rec structure, and increase by one 830N/A * its size is 64bits on some platforms (linux/alpha), and this caused problems with * Number of elements in the structure unique_id_rec. * Calculate the sizes and offsets in cur_unique_id. * Calculate the size of the structure when encoded. * Now get the global in_addr. Note that it is not sufficient to use one * of the addresses from the main_server, since those aren't as likely to * be unique as the physical address of the machine "mod_unique_id: unable to find hostname of the server");
/* XXX theoretically there are boxes out there which want to use * mod_unique_id but which have no IPv4 address... send in a patch :) "mod_unique_id: unable to find IPv4 address of \"%s\"",
str);
"mod_unique_id: using ip addr %s",
* If the server is pummelled with restart requests we could possibly end * up in a situation where we're starting again during the same second * that has been used in previous identifiers. Avoid that situation. * In truth, for this to actually happen not only would it have to restart * in the same second, but it would have to somehow get the same pids as * one of the other servers that was running in that second. Which would * mean a 64k wraparound on pids ... not very likely at all. * But protecting against it is relatively cheap. We just sleep into the * Note that we use the pid because it's possible that on the same * physical machine there are multiple servers (i.e. using Listen). But * it's guaranteed that none of them will share the same pids between * XXX: for multithread this needs to use a pid/tid combo and probably * needs to be expanded to 32 bits * Test our assumption that the pid is 32-bits. It's possible that * 64-bit machines will declare pid_t to be 64 bits but only use 32 * of them. It would have been really nice to test this during * global_init ... but oh well. "oh no! pids are greater than 32-bits! I'm broken!");
* If we use 0 as the initial counter we have a little less protection * against restart problems, and a little less protection against a clock * going backwards in time. /* Some systems have very low variance on the low end of their system * counter, defend against that. * We must always use network ordering for these bytes, so that * identifiers are comparable between machines of different byte * orderings. Note in_addr is already in network order. /* NOTE: This is *NOT* the same encoding used by base64encode ... the last two * characters should be + and /. But those two characters have very special * meanings in URLs, and we want to make it easy to use identifiers in * URLs. So we replace them with @ and -. 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'@',
'-',
* Buffer padded with two final bytes, used to copy the unique_id_red * structure without the internal paddings that it could have. /* copy the unique_id if this is an internal redirect (we're never * actually called for sub requests, so we don't need to test for /* we'll use a temporal buffer to avoid uuencoding the possible internal * paddings of the original structure */ * We reset two more bytes just in case padding is needed for the uuencoding. /* alloc str and do the uuencoding */ str[k++] =
uuencoder[((y[0] &
0x03) <<
4) | ((y[
1] &
0xf0) >>
4)];
str[k++] =
uuencoder[((y[
1] &
0x0f) <<
2) | ((y[
2] &
0xc0) >>
6)];
/* set the environment variable */ /* and increment the identifier for the next call */ NULL,
/* dir config creater */ NULL,
/* dir merger --- default is to override */ NULL,
/* server config */ NULL,
/* merge server configs */ NULL,
/* command apr_table_t */