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).
11 /****************************************************************
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 ****************************************************************/
28 static void dummy_destructor(struct open_request *req)
32 static struct or_calltable dummy =
41 static int redirect_sock (tux_req_t *req, const int port)
43 struct socket *sock = req->sock;
44 struct open_request *tcpreq;
45 struct sock *sk, *oldsk;
49 * Look up (optional) listening user-space socket.
52 sk = tcp_v4_lookup_listener(INADDR_ANY, port, 0);
54 * Look up localhost listeners as well.
58 ((unsigned char *)&daddr)[0] = 127;
59 ((unsigned char *)&daddr)[1] = 0;
60 ((unsigned char *)&daddr)[2] = 0;
61 ((unsigned char *)&daddr)[3] = 1;
62 sk = tcp_v4_lookup_listener(daddr, port, 0);
66 /* No secondary server found */
71 * Requeue the 'old' socket as an accept-socket of
72 * the listening socket. This way we can shuffle
73 * a socket around. Since we've read the input data
74 * via the non-destructive MSG_PEEK, the secondary
75 * server can be used transparently.
80 if (sk->sk_state != TCP_LISTEN)
83 tcpreq = tcp_openreq_alloc();
87 unlink_tux_socket(req);
90 sock->state = SS_UNCONNECTED;
92 tcpreq->class = &dummy;
93 write_lock_irq(&oldsk->sk_callback_lock);
94 oldsk->sk_socket = NULL;
95 oldsk->sk_sleep = NULL;
96 write_unlock_irq(&oldsk->sk_callback_lock);
98 tcp_sk(oldsk)->nonagle = 0;
100 tcp_acceptq_queue(sk, tcpreq, oldsk);
102 sk->sk_data_ready(sk, 0);
105 * It's now completely up to the secondary
106 * server to handle this request.
108 sock_release(req->sock);
112 Dprintk("req %p redirected to secondary server!\n", req);
119 Dprintk("NO secondary server for req %p!\n", req);
123 void redirect_request (tux_req_t *req, int cachemiss)
125 if (tux_TDprintk && (req->status != 304)) {
126 TDprintk("trying to redirect req %p, req->error: %d, req->status: %d.\n", req, req->error, req->status);
132 if (req->error == TUX_ERROR_CONN_CLOSE)
139 if (!req->proto->can_redirect || (req->status == 304) || redirect_sock(req, tux_clientport)) {
142 req->proto->illegal_request(req, cachemiss);
149 clear_keepalive(req);
150 if (!tux_redirect_logging)
152 flush_request(req, cachemiss);