⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vhost.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * http_vhost.c: functions pertaining to virtual host addresses *      (configuration and run-time) */#include "apr.h"#include "apr_strings.h"#include "apr_lib.h"#define APR_WANT_STRFUNC#include "apr_want.h"#define CORE_PRIVATE#include "ap_config.h"#include "httpd.h"#include "http_config.h"#include "http_log.h"#include "http_vhost.h"#include "http_protocol.h"#include "http_core.h"#if APR_HAVE_ARPA_INET_H#include <arpa/inet.h>#endif/* * After all the definitions there's an explanation of how it's all put * together. *//* meta-list of name-vhosts.  Each server_rec can be in possibly multiple * lists of name-vhosts. */typedef struct name_chain name_chain;struct name_chain {    name_chain *next;    server_addr_rec *sar;       /* the record causing it to be in                                 * this chain (needed for port comparisons) */    server_rec *server;         /* the server to use on a match */};/* meta-list of ip addresses.  Each server_rec can be in possibly multiple * hash chains since it can have multiple ips. */typedef struct ipaddr_chain ipaddr_chain;struct ipaddr_chain {    ipaddr_chain *next;    server_addr_rec *sar;       /* the record causing it to be in                                 * this chain (need for both ip addr and port                                 * comparisons) */    server_rec *server;         /* the server to use if this matches */    name_chain *names;          /* if non-NULL then a list of name-vhosts                                 * sharing this address */};/* This defines the size of the hash apr_table_t used for hashing ip addresses * of virtual hosts.  It must be a power of two. */#ifndef IPHASH_TABLE_SIZE#define IPHASH_TABLE_SIZE 256#endif/* A (n) bucket hash table, each entry has a pointer to a server rec and * a pointer to the other entries in that bucket.  Each individual address, * even for virtualhosts with multiple addresses, has an entry in this hash * table.  There are extra buckets for _default_, and name-vhost entries. * * Note that after config time this is constant, so it is thread-safe. */static ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];/* dump out statistics about the hash function *//* #define IPHASH_STATISTICS *//* list of the _default_ servers */static ipaddr_chain *default_list;/* list of the NameVirtualHost addresses */static server_addr_rec *name_vhost_list;static server_addr_rec **name_vhost_list_tail;/* * How it's used: * * The ip address determines which chain in iphash_table is interesting, then * a comparison is done down that chain to find the first ipaddr_chain whose * sar matches the address:port pair. * * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost. * * Otherwise it's a name-vhost list, and the default is the server in the * ipaddr_chain record.  We tuck away the ipaddr_chain record in the * conn_rec field vhost_lookup_data.  Later on after the headers we get a * second chance, and we use the name_chain to figure out what name-vhost * matches the headers. * * If there was no ip address match in the iphash_table then do a lookup * in the default_list. * * How it's put together ... well you should be able to figure that out * from how it's used.  Or something like that. *//* called at the beginning of the config */AP_DECLARE(void) ap_init_vhost_config(apr_pool_t *p){    memset(iphash_table, 0, sizeof(iphash_table));    default_list = NULL;    name_vhost_list = NULL;    name_vhost_list_tail = &name_vhost_list;}/* * Parses a host of the form <address>[:port] * paddr is used to create a list in the order of input * **paddr is the ->next pointer of the last entry (or s->addrs) * *paddr is the variable used to keep track of **paddr between calls * port is the default port to assume */static const char *get_addresses(apr_pool_t *p, const char *w_,                                 server_addr_rec ***paddr,                                  apr_port_t default_port){    apr_sockaddr_t *my_addr;    server_addr_rec *sar;    char *w, *host, *scope_id;    int wild_port;    apr_size_t wlen;    apr_port_t port;    apr_status_t rv;    if (*w_ == '\0')        return NULL;    w = apr_pstrdup(p, w_);    /* apr_parse_addr_port() doesn't understand ":*" so handle that first. */    wlen = strlen(w);                    /* wlen must be > 0 at this point */    wild_port = 0;    if (w[wlen - 1] == '*') {        if (wlen < 2) {            wild_port = 1;        }        else if (w[wlen - 2] == ':') {            w[wlen - 2] = '\0';            wild_port = 1;        }    }    rv = apr_parse_addr_port(&host, &scope_id, &port, w, p);    /* If the string is "80", apr_parse_addr_port() will be happy and set     * host to NULL and port to 80, so watch out for that.     */    if (rv != APR_SUCCESS) {        return "The address or port is invalid";    }    if (!host) {        return "Missing address for VirtualHost";    }    if (scope_id) {        return "Scope ids are not supported";    }    if (!port && !wild_port) {        port = default_port;    }    if (strcmp(host, "*") == 0) {        rv = apr_sockaddr_info_get(&my_addr, "0.0.0.0", APR_INET, port, 0, p);        ap_assert(rv == APR_SUCCESS); /* must be bug or out of storage */    }    else if (strcasecmp(host, "_default_") == 0        || strcmp(host, "255.255.255.255") == 0) {        rv = apr_sockaddr_info_get(&my_addr, "255.255.255.255", APR_INET, port, 0, p);        ap_assert(rv == APR_SUCCESS); /* must be bug or out of storage */    }    else {        rv = apr_sockaddr_info_get(&my_addr, host, APR_UNSPEC, port, 0, p);        if (rv != APR_SUCCESS) {            ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,                "Cannot resolve host name %s --- ignoring!", host);            return NULL;        }    }    /* Remember all addresses for the host */    do {        sar = apr_pcalloc(p, sizeof(server_addr_rec));        **paddr = sar;        *paddr = &sar->next;        sar->host_addr = my_addr;        sar->host_port = port;        sar->virthost = host;        my_addr = my_addr->next;    } while (my_addr);    return NULL;}/* parse the <VirtualHost> addresses */const char *ap_parse_vhost_addrs(apr_pool_t *p,                                 const char *hostname,                                 server_rec *s){    server_addr_rec **addrs;    const char *err;    /* start the list of addreses */    addrs = &s->addrs;    while (hostname[0]) {        err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);        if (err) {            *addrs = NULL;            return err;        }    }    /* terminate the list */    *addrs = NULL;    if (s->addrs) {        if (s->addrs->host_port) {            /* override the default port which is inherited from main_server */            s->port = s->addrs->host_port;        }    }    return NULL;}const char *ap_set_name_virtual_host(cmd_parms *cmd, void *dummy,                                     const char *arg){    /* use whatever port the main server has at this point */    return get_addresses(cmd->pool, arg, &name_vhost_list_tail,                         cmd->server->port);}/* hash apr_table_t statistics, keep this in here for the beta period so * we can find out if the hash function is ok */#ifdef IPHASH_STATISTICSstatic int iphash_compare(const void *a, const void *b){    return (*(const int *) b - *(const int *) a);}static void dump_iphash_statistics(server_rec *main_s){    unsigned count[IPHASH_TABLE_SIZE];    int i;    ipaddr_chain *src;    unsigned total;    char buf[HUGE_STRING_LEN];    char *p;    total = 0;    for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {        count[i] = 0;        for (src = iphash_table[i]; src; src = src->next) {            ++count[i];            if (i < IPHASH_TABLE_SIZE) {                /* don't count the slop buckets in the total */                ++total;            }        }    }    qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);    p = buf + apr_snprintf(buf, sizeof(buf),                           "iphash: total hashed = %u, avg chain = %u, "                           "chain lengths (count x len):",                           total, total / IPHASH_TABLE_SIZE);    total = 1;    for (i = 1; i < IPHASH_TABLE_SIZE; ++i) {        if (count[i - 1] != count[i]) {            p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",                              total, count[i - 1]);            total = 1;        }        else {            ++total;        }    }    p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",                      total, count[IPHASH_TABLE_SIZE - 1]);    ap_log_error(APLOG_MARK, APLOG_DEBUG, main_s, buf);}#endif/* This hashing function is designed to get good distribution in the cases * where the server is handling entire "networks" of servers.  i.e. a * whack of /24s.  This is probably the most common configuration for * ISPs with large virtual servers. * * NOTE: This function is symmetric (i.e. collapses all 4 octets * into one), so machine byte order (big/little endianness) does not matter. * * Hash function provided by David Hankins. */static APR_INLINE unsigned hash_inaddr(unsigned key){    key ^= (key >> 16);    return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;}static APR_INLINE unsigned hash_addr(struct apr_sockaddr_t *sa){    unsigned key;    /* The key is the last four bytes of the IP address.     * For IPv4, this is the entire address, as always.     * For IPv6, this is usually part of the MAC address.     */    key = *(unsigned *)((char *)sa->ipaddr_ptr + sa->ipaddr_len - 4);    return hash_inaddr(key);}static ipaddr_chain *new_ipaddr_chain(apr_pool_t *p,                                      server_rec *s, server_addr_rec *sar){    ipaddr_chain *new;    new = apr_palloc(p, sizeof(*new));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -