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_process_delete(&r
->proc
);
32 ustream_free(&r
->sfd
.stream
);
38 void uh_relay_close(struct relay
*r
, int ret
)
40 struct ustream
*us
= &r
->sfd
.stream
;
45 us
->notify_read
= NULL
;
46 us
->notify_write
= NULL
;
47 us
->notify_state
= NULL
;
53 static void relay_error(struct relay
*r
)
55 struct ustream
*s
= &r
->sfd
.stream
;
59 ustream_get_read_buf(s
, &len
);
61 ustream_consume(s
, len
);
62 ustream_state_change(s
);
65 static void relay_process_headers(struct relay
*r
)
67 struct ustream
*s
= &r
->sfd
.stream
;
74 while (r
->header_cb
) {
78 buf
= ustream_get_read_buf(s
, &len
);
82 newline
= strchr(buf
, '\n');
86 line_len
= newline
+ 1 - buf
;
87 if (newline
> buf
&& newline
[-1] == '\r')
95 ustream_consume(s
, line_len
);
99 val
= uh_split_header(buf
);
105 r
->header_cb(r
, buf
, val
);
106 ustream_consume(s
, line_len
);
110 static void relay_read_cb(struct ustream
*s
, int bytes
)
112 struct relay
*r
= container_of(s
, struct relay
, sfd
.stream
);
113 struct client
*cl
= r
->cl
;
114 struct ustream
*us
= cl
->us
;
119 uloop_timeout_set(&r
->timeout
, 1);
121 relay_process_headers(r
);
125 * if eof, ensure that remaining data is discarded, so the
126 * state change cb will tear down the stream
133 if (!s
->eof
&& ustream_pending_data(us
, true)) {
134 ustream_set_read_blocked(s
, true);
138 buf
= ustream_get_read_buf(s
, &len
);
142 uh_chunk_write(cl
, buf
, len
);
143 ustream_consume(s
, len
);
146 static void relay_close_if_done(struct uloop_timeout
*timeout
)
148 struct relay
*r
= container_of(timeout
, struct relay
, timeout
);
149 struct ustream
*s
= &r
->sfd
.stream
;
151 while (ustream_poll(&r
->sfd
.stream
));
153 if (!(r
->process_done
|| s
->eof
) || ustream_pending_data(s
, false))
156 uh_relay_close(r
, r
->ret
);
159 static void relay_state_cb(struct ustream
*s
)
161 struct relay
*r
= container_of(s
, struct relay
, sfd
.stream
);
164 uloop_timeout_set(&r
->timeout
, 1);
167 static void relay_proc_cb(struct uloop_process
*proc
, int ret
)
169 struct relay
*r
= container_of(proc
, struct relay
, proc
);
171 r
->process_done
= true;
173 uloop_timeout_set(&r
->timeout
, 1);
176 void uh_relay_kill(struct client
*cl
, struct relay
*r
)
178 struct ustream
*us
= &r
->sfd
.stream
;
180 kill(r
->proc
.pid
, SIGKILL
);
182 ustream_state_change(us
);
185 void uh_relay_open(struct client
*cl
, struct relay
*r
, int fd
, int pid
)
187 struct ustream
*us
= &r
->sfd
.stream
;
190 us
->notify_read
= relay_read_cb
;
191 us
->notify_state
= relay_state_cb
;
192 us
->string_data
= true;
193 ustream_fd_init(&r
->sfd
, fd
);
196 r
->proc
.cb
= relay_proc_cb
;
197 uloop_process_add(&r
->proc
);
199 r
->timeout
.cb
= relay_close_if_done
;