Hi,
since everybody seems to be away for the weekend I've investigated the
problems outlined in the last mail myself. Please find the result attached.
The MPM is now able to detect whether the incoming connection is for an
IP based or a name based vhost. If it is an IP based vhost it is not
parsed by the multiplexer and directly forwarded to the worker process
of the vhost. For non SSL vhosts this will increase the performance of
the server, for SSL vhosts it will allow them to work properly. Name
based, non-SSL vhosts will be served the same way it would have been
done without this patch. This addresses points one & two raised in the
last email.
Apart from needing additional review the patch should be complete now.
To apply simply issue the following command in your source directory
with the peruser patch already applied:
# patch server/mpm/experimental/peruser/peruser.c < peruser-ssl2.patch
Any feedback is highly appreciated.
Stefan
--- peruser-orig.c 2006-03-04 19:30:18.000000000 +0100
+++ peruser.c 2006-03-05 15:33:09.000000000 +0100
@@ -66,7 +66,7 @@
#include "apr_strings.h"
#include "apr_thread_proc.h"
#include "apr_signal.h"
-
+#include "arch/unix/apr_arch_networkio.h"
#define APR_WANT_STDIO
#define APR_WANT_STRFUNC
#define APR_WANT_IOVEC
@@ -820,13 +820,159 @@
return 0;
}
+/*
+ * This function sends a raw socket over to a processor. It uses the same
+ * on-wire format as pass_request. The recipient can determine if he got
+ * a socket or a whole request by inspecting the header_length of the
+ * message. If it is zero then only a socket was sent.
+ */
+static int pass_socket(apr_socket_t *thesock, child_info_t *processor,
apr_pool_t *pool)
+{
+ int rv;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ int sock_fd;
+ char *body = "";
+ struct iovec iov[4];
+ apr_size_t len = 0;
+ apr_size_t header_len = 0;
+ apr_size_t body_len = 0;
+ peruser_header h;
+ apr_bucket *bucket;
+ const apr_array_header_t *headers_in_array;
+ const apr_table_entry_t *headers_in;
+ int counter;
+
+ if (!processor)
+ {
+ _DBG("server %s in child %d has no child_info associated",
+ "(unkonwn)", my_child_num);
+ return -1;
+ }
+
+ _DBG("passing request to another child.", 0);
+
+ apr_os_sock_get(&sock_fd, thesock);
+
+ header_len = 0;
+ body_len = 0;
+
+ iov[0].iov_base = &header_len;
+ iov[0].iov_len = sizeof(header_len);
+ iov[1].iov_base = &body_len;
+ iov[1].iov_len = sizeof(body_len);
+ iov[2].iov_base = h.headers;
+ iov[2].iov_len = 0;
+ iov[3].iov_base = body;
+ iov[3].iov_len = body_len;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 4;
+
+ cmsg = apr_palloc(pool, sizeof(*cmsg) + sizeof(sock_fd));
+ cmsg->cmsg_len = sizeof(*cmsg) + sizeof(sock_fd);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+
+ memcpy(CMSG_DATA(cmsg), &sock_fd, sizeof(sock_fd));
+
+ msg.msg_control = cmsg;
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ if (processor->status == CHILD_STATUS_STANDBY)
+ {
+ _DBG("Activating child #%d", processor->id);
+ processor->status = CHILD_STATUS_STARTING;
+ }
+
+ while (processor->status != CHILD_STATUS_ACTIVE)
+ {
+ _DBG("Waiting for child #%d...", processor->id);
+ sleep(1);
+ }
+
+ _DBG("Writing message to %d, passing sock_fd: %d",
processor->senv->output, sock_fd);
+ _DBG("header_len=%d headers=\"%s\"", header_len, h.headers);
+ _DBG("body_len=%d body=\"%s\"", body_len, body);
+
+ if ((rv = sendmsg(processor->senv->output, &msg, 0)) == -1)
+ {
+ apr_pool_destroy(pool);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
+ "Writing message failed %d %d", rv, errno);
+ return -1;
+ }
+
+ _DBG("Writing message succeeded %d", rv);
+
+ /* -- close the socket on our side -- */
+ _DBG("closing socket %d on our side", sock_fd);
+ apr_socket_close(thesock);
+
+ apr_pool_destroy(pool);
+ return 1;
+}
+
static void process_socket(apr_pool_t *p, apr_socket_t *sock, long conn_id,
- apr_bucket_alloc_t *bucket_alloc)
+ apr_bucket_alloc_t *bucket_alloc, apr_pool_t *pool)
{
conn_rec *current_conn;
int sock_fd;
apr_status_t rv;
ap_sb_handle_t *sbh;
+ apr_sockaddr_t *local_addr;
+ child_info_t *processor;
+ apr_pool_t *ptrans;
+ peruser_server_conf *sconf;
+
+ local_addr = (apr_sockaddr_t*)sock->local_addr;
+
+ _DBG("Creating dummy connection to use the vhost lookup api", 0);
+
+ ap_create_sb_handle(&sbh, p, conn_id, 0);
+ current_conn = ap_run_create_connection(p, ap_server_conf, sock, conn_id,
+ sbh, bucket_alloc);
+ _DBG("Looking up the right vhost");
+ ap_update_vhost_given_ip(current_conn);
+ _DBG("Base server is %s, name based vhosts %s",
current_conn->base_server->server_hostname,
+ current_conn->vhost_lookup_data ? "on" : "off");
+
+
+ if (!current_conn->vhost_lookup_data &&
CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
+ _DBG("We are not using name based vhosts, we'll directly pass the
socket.");
+
+ sconf = PERUSER_SERVER_CONF(current_conn->base_server->module_config);
+ processor = &CHILD_INFO_TABLE[sconf->senv->processor_id];
+
+ //processor = &CHILD_INFO_TABLE[1]; // FIXME: Lookup the right
processor!
+ _DBG("Forwarding without further inspection, processor %d",
processor->id);
+ if (processor->status == CHILD_STATUS_STANDBY)
+ {
+ _DBG("Activating child #%d", processor->id);
+ processor->status = CHILD_STATUS_STARTING;
+ }
+
+ _DBG("Creating new pool",0);
+ apr_pool_create(&ptrans, pool);
+ _DBG("Passing request.",0);
+ if (pass_socket(sock, processor, ptrans) == -1)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0,
+ ap_server_conf, "Could not pass request to proper "
+ "child, request will not be honoured.");
+ return;
+ }
+ if (current_conn)
+ {
+ _DBG("freeing connection",0);
+ ap_lingering_close(current_conn);
+ }
+ _DBG("doing longjmp",0);
+ longjmp(CHILD_INFO_TABLE[my_child_num].jmpbuffer, 1);
+ return;
+ }
if ((rv = apr_os_sock_get(&sock_fd, sock)) != APR_SUCCESS)
{
@@ -853,9 +999,11 @@
ap_sock_disable_nagle(sock);
}
- ap_create_sb_handle(&sbh, p, conn_id, 0);
- current_conn = ap_run_create_connection(p, ap_server_conf, sock, conn_id,
- sbh, bucket_alloc);
+ if (!current_conn) {
+ ap_create_sb_handle(&sbh, p, conn_id, 0);
+ current_conn = ap_run_create_connection(p, ap_server_conf, sock,
conn_id,
+ sbh, bucket_alloc);
+ }
if (current_conn)
{
@@ -1135,6 +1283,8 @@
apr_cpystrn(headers, buff, header_len + 1);
_DBG("header_len=%d headers=\"%s\"", header_len, headers);
+if (header_len) {
+ _DBG("header_len > 0, we got a request", 0);
/* -- store received data into an brigade and add
it to the current transaction's pool -- */
bucket = apr_bucket_eos_create(alloc);
@@ -1156,7 +1306,9 @@
APR_BRIGADE_INSERT_HEAD(bb, bucket);
apr_pool_userdata_set(bb, "PERUSER_SOCKETS", NULL, ptrans);
-
+} else {
+ _DBG("header_len == 0, we got a socket only", 0);
+}
_DBG("returning 0", 0);
return 0;
}
@@ -1563,7 +1715,7 @@
{
_DBG("marked jmpbuffer",0);
_TRACE_CALL("process_socket()",0);
- process_socket(ptrans, sock, my_child_num, bucket_alloc);
+ process_socket(ptrans, sock, my_child_num, bucket_alloc, pchild);
_TRACE_RET("process_socket()",0);
}
else
_______________________________________________
Peruser mailing list
[email protected]
http://www.telana.com/mailman/listinfo/peruser