2 * uhttpd - Tiny single-threaded httpd
4 * Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
5 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 void uh_relay_free(struct relay *r)
29 kill(r->proc.pid, SIGKILL);
31 uloop_timeout_cancel(&r->timeout);
32 uloop_process_delete(&r->proc);
33 ustream_free(&r->sfd.stream);
39 void uh_relay_close(struct relay *r, int ret)
41 struct ustream *us = &r->sfd.stream;
46 us->notify_read = NULL;
47 us->notify_write = NULL;
48 us->notify_state = NULL;
54 static void relay_error(struct relay *r)
56 struct ustream *s = &r->sfd.stream;
61 ustream_get_read_buf(s, &len);
63 ustream_consume(s, len);
64 ustream_state_change(s);
67 static void relay_process_headers(struct relay *r)
69 struct ustream *s = &r->sfd.stream;
76 while (r->header_cb) {
80 buf = ustream_get_read_buf(s, &len);
84 newline = strchr(buf, '\n');
88 line_len = newline + 1 - buf;
89 if (newline > buf && newline[-1] == '\r')
97 ustream_consume(s, line_len);
101 val = uh_split_header(buf);
107 r->header_cb(r, buf, val);
108 ustream_consume(s, line_len);
112 static void relay_read_cb(struct ustream *s, int bytes)
114 struct relay *r = container_of(s, struct relay, sfd.stream);
115 struct client *cl = r->cl;
116 struct ustream *us = cl->us;
121 uloop_timeout_set(&r->timeout, 1);
124 relay_process_headers(r);
128 * if eof, ensure that remaining data is discarded, so the
129 * state change cb will tear down the stream
136 if (!s->eof && ustream_pending_data(us, true)) {
137 ustream_set_read_blocked(s, true);
141 buf = ustream_get_read_buf(s, &len);
146 uh_chunk_write(cl, buf, len);
148 ustream_consume(s, len);
151 static void relay_close_if_done(struct uloop_timeout *timeout)
153 struct relay *r = container_of(timeout, struct relay, timeout);
154 struct ustream *s = &r->sfd.stream;
156 while (ustream_poll(&r->sfd.stream));
158 if (!(r->process_done || s->eof) || ustream_pending_data(s, false))
161 uh_relay_close(r, r->ret);
164 static void relay_state_cb(struct ustream *s)
166 struct relay *r = container_of(s, struct relay, sfd.stream);
169 uloop_timeout_set(&r->timeout, 1);
172 static void relay_proc_cb(struct uloop_process *proc, int ret)
174 struct relay *r = container_of(proc, struct relay, proc);
176 r->process_done = true;
178 uloop_timeout_set(&r->timeout, 1);
181 void uh_relay_kill(struct client *cl, struct relay *r)
183 struct ustream *us = &r->sfd.stream;
185 kill(r->proc.pid, SIGKILL);
187 ustream_state_change(us);
190 void uh_relay_open(struct client *cl, struct relay *r, int fd, int pid)
192 struct ustream *us = &r->sfd.stream;
195 us->notify_read = relay_read_cb;
196 us->notify_state = relay_state_cb;
197 us->string_data = true;
198 ustream_fd_init(&r->sfd, fd);
201 r->proc.cb = relay_proc_cb;
202 uloop_process_add(&r->proc);
204 r->timeout.cb = relay_close_if_done;