proxy_util.c
来自「apache服务器源代码(版本号:2.2.2)」· C语言 代码 · 共 2,057 行 · 第 1/5 页
C
2,057 行
if (worker->route) strcpy(worker->s->route, worker->route); else *worker->s->route = '\0'; if (worker->redirect) strcpy(worker->s->redirect, worker->redirect); else *worker->s->redirect = '\0'; worker->s->status |= (worker->status | PROXY_WORKER_INITIALIZED);}PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, server_rec *s){ apr_status_t rv;#if APR_HAS_THREADS int mpm_threads;#endif if (worker->status & PROXY_WORKER_INITIALIZED) { /* The worker is already initialized */ return APR_SUCCESS; } /* Set default parameters */ if (!worker->retry) worker->retry = apr_time_from_sec(PROXY_WORKER_DEFAULT_RETRY); /* By default address is reusable */ worker->is_address_reusable = 1;#if APR_HAS_THREADS ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads); if (mpm_threads > 1) { /* Set hard max to no more then mpm_threads */ if (worker->hmax == 0 || worker->hmax > mpm_threads) worker->hmax = mpm_threads; if (worker->smax == 0 || worker->smax > worker->hmax) worker->smax = worker->hmax; /* Set min to be lower then smax */ if (worker->min > worker->smax) worker->min = worker->smax; } else { /* This will supress the apr_reslist creation */ worker->min = worker->smax = worker->hmax = 0; } if (worker->hmax) { rv = apr_reslist_create(&(worker->cp->res), worker->min, worker->smax, worker->hmax, worker->ttl, connection_constructor, connection_destructor, worker, worker->cp->pool); apr_pool_cleanup_register(worker->cp->pool, (void *)worker, conn_pool_cleanup, apr_pool_cleanup_null); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: initialized worker %d in child %" APR_PID_T_FMT " for (%s) min=%d max=%d smax=%d", worker->id, getpid(), worker->hostname, worker->min, worker->hmax, worker->smax);#if (APR_MAJOR_VERSION > 0) /* Set the acquire timeout */ if (rv == APR_SUCCESS && worker->acquire_set) apr_reslist_timeout_set(worker->cp->res, worker->acquire);#endif } else#endif { rv = connection_constructor((void **)&(worker->cp->conn), worker, worker->cp->pool); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: initialized single connection worker %d in child %" APR_PID_T_FMT " for (%s)", worker->id, getpid(), worker->hostname); } if (rv == APR_SUCCESS) { worker->status |= (PROXY_WORKER_INITIALIZED); } return rv;}PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function, proxy_worker *worker, server_rec *s){ if (worker->s->status & PROXY_WORKER_IN_ERROR) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: retrying the worker for (%s)", proxy_function, worker->hostname); if (apr_time_now() > worker->s->error_time + worker->retry) { ++worker->s->retries; worker->s->status &= ~PROXY_WORKER_IN_ERROR; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: worker for (%s) has been marked for retry", proxy_function, worker->hostname); return OK; } else return DECLINED; } else return OK;}PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function, proxy_conn_rec **conn, proxy_worker *worker, server_rec *s){ apr_status_t rv; if (!PROXY_WORKER_IS_USABLE(worker)) { /* Retry the worker */ ap_proxy_retry_worker(proxy_function, worker, s); if (!PROXY_WORKER_IS_USABLE(worker)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "proxy: %s: disabled connection for (%s)", proxy_function, worker->hostname); return HTTP_SERVICE_UNAVAILABLE; } }#if APR_HAS_THREADS if (worker->hmax && worker->cp->res) { rv = apr_reslist_acquire(worker->cp->res, (void **)conn); } else#endif { /* create the new connection if the previous was destroyed */ if (!worker->cp->conn) connection_constructor((void **)conn, worker, worker->cp->pool); else { *conn = worker->cp->conn; worker->cp->conn = NULL; } rv = APR_SUCCESS; } if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "proxy: %s: failed to acquire connection for (%s)", proxy_function, worker->hostname); return HTTP_SERVICE_UNAVAILABLE; } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: has acquired connection for (%s)", proxy_function, worker->hostname); (*conn)->worker = worker; (*conn)->close = 0; (*conn)->close_on_recycle = 0;#if APR_HAS_THREADS (*conn)->inreslist = 0;#endif return OK;}PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function, proxy_conn_rec *conn, server_rec *s){ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: has released connection for (%s)", proxy_function, conn->worker->hostname); /* If there is a connection kill it's cleanup */ if (conn->connection) { apr_pool_cleanup_kill(conn->connection->pool, conn, connection_cleanup); conn->connection = NULL; } connection_cleanup(conn); return OK;}PROXY_DECLARE(int)ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, proxy_server_conf *conf, proxy_worker *worker, proxy_conn_rec *conn, apr_uri_t *uri, char **url, const char *proxyname, apr_port_t proxyport, char *server_portstr, int server_portstr_size){ int server_port; apr_status_t err = APR_SUCCESS; /* * Break up the URL to determine the host to connect to */ /* we break the URL into host, port, uri */ if (APR_SUCCESS != apr_uri_parse(p, *url, uri)) { return ap_proxyerror(r, HTTP_BAD_REQUEST, apr_pstrcat(p,"URI cannot be parsed: ", *url, NULL)); } if (!uri->port) { uri->port = apr_uri_port_of_scheme(uri->scheme); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: connecting %s to %s:%d", *url, uri->hostname, uri->port); /* * allocate these out of the specified connection pool * The scheme handler decides if this is permanent or * short living pool. */ /* are we connecting directly, or via a proxy? */ if (!proxyname) { *url = apr_pstrcat(p, uri->path, uri->query ? "?" : "", uri->query ? uri->query : "", uri->fragment ? "#" : "", uri->fragment ? uri->fragment : "", NULL); } /* * Make sure that we pick the the correct and valid worker. * If a single keepalive connection triggers different workers, * then we have a problem (we don't select the correct one). * Do an expensive check in this case, where we compare the * the hostnames associated between the two. * * TODO: Handle this much better... */ if (!conn->hostname || !worker->is_address_reusable || (r->connection->keepalives && (r->proxyreq == PROXYREQ_PROXY || r->proxyreq == PROXYREQ_REVERSE) && (strcasecmp(conn->hostname, uri->hostname) != 0) ) ) { if (proxyname) { conn->hostname = apr_pstrdup(conn->pool, proxyname); conn->port = proxyport; } else { conn->hostname = apr_pstrdup(conn->pool, uri->hostname); conn->port = uri->port; } if (conn->sock) { apr_socket_close(conn->sock); conn->sock = NULL; } if (conn->connection) { apr_pool_cleanup_kill(conn->connection->pool, conn, connection_cleanup); conn->connection = NULL; } err = apr_sockaddr_info_get(&(conn->addr), conn->hostname, APR_UNSPEC, conn->port, 0, conn->pool); } else if (!worker->cp->addr) { if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, err, r->server, "proxy: lock"); return HTTP_INTERNAL_SERVER_ERROR; } /* * Worker can have the single constant backend adress. * The single DNS lookup is used once per worker. * If dynamic change is needed then set the addr to NULL * inside dynamic config to force the lookup. */ err = apr_sockaddr_info_get(&(worker->cp->addr), conn->hostname, APR_UNSPEC, conn->port, 0, worker->cp->pool); conn->addr = worker->cp->addr; PROXY_THREAD_UNLOCK(worker); } else conn->addr = worker->cp->addr; if (err != APR_SUCCESS) { return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p, "DNS lookup failure for: ", conn->hostname, NULL)); } /* Get the server port for the Via headers */ { server_port = ap_get_server_port(r); if (ap_is_default_port(server_port, r)) { strcpy(server_portstr,""); } else { apr_snprintf(server_portstr, server_portstr_size, ":%d", server_port); } } /* check if ProxyBlock directive on this host */ if (OK != ap_proxy_checkproxyblock(r, conf, conn->addr)) { return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: connected %s to %s:%d", *url, conn->hostname, conn->port); return OK;}static int is_socket_connected(apr_socket_t *sock){ apr_size_t buffer_len = 1; char test_buffer[1]; apr_status_t socket_status; apr_interval_time_t current_timeout; /* save timeout */ apr_socket_timeout_get(sock, ¤t_timeout); /* set no timeout */ apr_socket_timeout_set(sock, 0); socket_status = apr_socket_recv(sock, test_buffer, &buffer_len); /* put back old timeout */ apr_socket_timeout_set(sock, current_timeout); if (APR_STATUS_IS_EOF(socket_status)) return 0; else return 1;}PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, proxy_conn_rec *conn, proxy_worker *worker, server_rec *s){ apr_status_t rv; int connected = 0; int loglevel; apr_sockaddr_t *backend_addr = conn->addr; apr_socket_t *newsock; if (conn->sock) { /* * This increases the connection pool size * but the number of dropped connections is * relatively small compared to connection lifetime */ if (!(connected = is_socket_connected(conn->sock))) { apr_socket_close(conn->sock); conn->sock = NULL; } } while (backend_addr && !connected) { if ((rv = apr_socket_create(&newsock, backend_addr->family, SOCK_STREAM, APR_PROTO_TCP, conn->pool)) != APR_SUCCESS) { loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; ap_log_error(APLOG_MARK, loglevel, rv, s, "proxy: %s: error creating fam %d socket for target %s", proxy_function, backend_addr->family, worker->hostname); /* * this could be an IPv6 address from the DNS but the * local machine won't give us an IPv6 socket; hopefully the * DNS returned an additional address to try */ backend_addr = backend_addr->next; continue; }#if !defined(TPF) && !defined(BEOS) if (worker->recv_buffer_size > 0 && (rv = apr_socket_opt_set(newsock, APR_SO_RCVBUF, worker->recv_buffer_size))) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "apr_socket_opt_set(SO_RCVBUF): Failed to set " "ProxyReceiveBufferSize, using default"); }#endif /* Set a timeout on the socket */ if (worker->timeout_set == 1) { apr_socket_timeout_set(newsock, worker->timeout); } else { apr_socket_timeout_set(newsock, s->timeout); } /* Set a keepalive option */ if (worker->keepalive) { if ((rv = apr_socket_opt_set(newsock, APR_SO_KEEPALIVE, 1)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "apr_socket_opt_set(SO_KEEPALIVE): Failed to set" " Keepalive"); } } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: fam %d socket created to connect to %s", proxy_function, backend_addr->family, worker->hostname); /* make the connection out of the socket */ rv = apr_socket_connect(newsock, backend_addr); /* if an error occurred, loop round and try again */ if (rv != APR_SUCCESS) { apr_socket_close(newsock); loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; ap_log_error(APLOG_MARK, loglevel, rv, s,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?