2 * TUX - Integrated Application Protocols Layer and Object Cache
4 * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
6 * redirect.c: redirect requests to other server sockets (such as Apache).
10 #include <linux/module.h>
11 #include <linux/init.h>
13 /****************************************************************
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 ****************************************************************/
30 static void nop_destructor(struct request_sock *req)
34 static struct request_sock_ops tux_req =
36 .destructor = &nop_destructor,
39 static int redirect_sock (tux_req_t *req, const int port)
41 struct socket *sock = req->sock;
42 struct request_sock *tcpreq;
43 struct sock *sk, *oldsk;
47 * Look up (optional) listening user-space socket.
50 sk = inet_lookup_listener(&tcp_hashinfo, INADDR_ANY, port, 0);
52 * Look up localhost listeners as well.
56 ((unsigned char *)&daddr)[0] = 127;
57 ((unsigned char *)&daddr)[1] = 0;
58 ((unsigned char *)&daddr)[2] = 0;
59 ((unsigned char *)&daddr)[3] = 1;
60 sk = inet_lookup_listener(&tcp_hashinfo, daddr, port, 0);
64 /* No secondary server found */
67 if (sk->sk_family != AF_INET) {
73 * Requeue the 'old' socket as an accept-socket of
74 * the listening socket. This way we can shuffle
75 * a socket around. Since we've read the input data
76 * via the non-destructive MSG_PEEK, the secondary
77 * server can be used transparently.
82 if (sk->sk_state != TCP_LISTEN)
85 tcpreq = reqsk_alloc(&tux_req);
89 unlink_tux_socket(req);
92 sock->state = SS_UNCONNECTED;
94 write_lock_irq(&oldsk->sk_callback_lock);
95 oldsk->sk_socket = NULL;
96 oldsk->sk_sleep = NULL;
97 write_unlock_irq(&oldsk->sk_callback_lock);
99 tcp_sk(oldsk)->nonagle = 0;
101 inet_csk_reqsk_queue_add(sk, tcpreq, oldsk);
103 sk->sk_data_ready(sk, 0);
106 * It's now completely up to the secondary
107 * server to handle this request.
113 sock_release(req->sock);
117 Dprintk("req %p redirected to secondary server!\n", req);
124 Dprintk("NO secondary server for req %p!\n", req);
128 void redirect_request (tux_req_t *req, int cachemiss)
130 if (tux_TDprintk && (req->status != 304)) {
131 TDprintk("trying to redirect req %p, req->error: %d, req->status: %d.\n", req, req->error, req->status);
137 if (req->error == TUX_ERROR_CONN_CLOSE)
144 if (!req->proto->can_redirect || (req->status == 304) || redirect_sock(req, tux_clientport)) {
147 req->proto->illegal_request(req, cachemiss);
154 clear_keepalive(req);
155 if (!tux_redirect_logging)
157 flush_request(req, cachemiss);
160 int init_tux_request_slabs(void)
162 tux_req.slab = kmem_cache_create("tux-request",
163 sizeof(struct request_sock), 0, SLAB_HWCACHE_ALIGN,
166 return tux_req.slab == NULL;
169 void free_tux_request_slabs(void)
171 kmem_cache_destroy(tux_req.slab);