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
;