0540bd8e58d29d118293fc466becd8db6260b0be
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
;
60 ustream_get_read_buf(s
, &len
);
62 ustream_consume(s
, len
);
63 ustream_state_change(s
);
66 static void relay_process_headers(struct relay
*r
)
68 struct ustream
*s
= &r
->sfd
.stream
;
75 while (r
->header_cb
) {
79 buf
= ustream_get_read_buf(s
, &len
);
83 newline
= strchr(buf
, '\n');
87 line_len
= newline
+ 1 - buf
;
88 if (newline
> buf
&& newline
[-1] == '\r')
96 ustream_consume(s
, line_len
);
100 val
= uh_split_header(buf
);
106 r
->header_cb(r
, buf
, val
);
107 ustream_consume(s
, line_len
);
111 static void relay_read_cb(struct ustream
*s
, int bytes
)
113 struct relay
*r
= container_of(s
, struct relay
, sfd
.stream
);
114 struct client
*cl
= r
->cl
;
115 struct ustream
*us
= cl
->us
;
120 uloop_timeout_set(&r
->timeout
, 1);
123 relay_process_headers(r
);
127 * if eof, ensure that remaining data is discarded, so the
128 * state change cb will tear down the stream
135 if (!s
->eof
&& ustream_pending_data(us
, true)) {
136 ustream_set_read_blocked(s
, true);
140 buf
= ustream_get_read_buf(s
, &len
);
144 uh_chunk_write(cl
, buf
, len
);
145 ustream_consume(s
, len
);
148 static void relay_close_if_done(struct uloop_timeout
*timeout
)
150 struct relay
*r
= container_of(timeout
, struct relay
, timeout
);
151 struct ustream
*s
= &r
->sfd
.stream
;
153 while (ustream_poll(&r
->sfd
.stream
));
155 if (!(r
->process_done
|| s
->eof
) || ustream_pending_data(s
, false))
158 uh_relay_close(r
, r
->ret
);
161 static void relay_state_cb(struct ustream
*s
)
163 struct relay
*r
= container_of(s
, struct relay
, sfd
.stream
);
166 uloop_timeout_set(&r
->timeout
, 1);
169 static void relay_proc_cb(struct uloop_process
*proc
, int ret
)
171 struct relay
*r
= container_of(proc
, struct relay
, proc
);
173 r
->process_done
= true;
175 uloop_timeout_set(&r
->timeout
, 1);
178 void uh_relay_kill(struct client
*cl
, struct relay
*r
)
180 struct ustream
*us
= &r
->sfd
.stream
;
182 kill(r
->proc
.pid
, SIGKILL
);
184 ustream_state_change(us
);
187 void uh_relay_open(struct client
*cl
, struct relay
*r
, int fd
, int pid
)
189 struct ustream
*us
= &r
->sfd
.stream
;
192 us
->notify_read
= relay_read_cb
;
193 us
->notify_state
= relay_state_cb
;
194 us
->string_data
= true;
195 ustream_fd_init(&r
->sfd
, fd
);
198 r
->proc
.cb
= relay_proc_cb
;
199 uloop_process_add(&r
->proc
);
201 r
->timeout
.cb
= relay_close_if_done
;