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
);
79 newline
= strchr(buf
, '\n');
83 line_len
= newline
+ 1 - buf
;
84 if (newline
> buf
&& newline
[-1] == '\r')
92 ustream_consume(s
, line_len
);
96 val
= uh_split_header(buf
);
102 r
->header_cb(r
, buf
, val
);
103 ustream_consume(s
, line_len
);
107 static void relay_read_cb(struct ustream
*s
, int bytes
)
109 struct relay
*r
= container_of(s
, struct relay
, sfd
.stream
);
110 struct client
*cl
= r
->cl
;
111 struct ustream
*us
= cl
->us
;
115 relay_process_headers(r
);
119 * if eof, ensure that remaining data is discarded, so the
120 * state change cb will tear down the stream
127 if (!s
->eof
&& ustream_pending_data(us
, true)) {
128 ustream_set_read_blocked(s
, true);
132 buf
= ustream_get_read_buf(s
, &len
);
136 uh_chunk_write(cl
, buf
, len
);
137 ustream_consume(s
, len
);
140 static void relay_close_if_done(struct relay
*r
)
142 struct ustream
*s
= &r
->sfd
.stream
;
144 if (!s
->eof
|| ustream_pending_data(s
, false))
147 uh_relay_close(r
, r
->ret
);
150 static void relay_state_cb(struct ustream
*s
)
152 struct relay
*r
= container_of(s
, struct relay
, sfd
.stream
);
155 relay_close_if_done(r
);
158 static void relay_proc_cb(struct uloop_process
*proc
, int ret
)
160 struct relay
*r
= container_of(proc
, struct relay
, proc
);
162 ustream_poll(&r
->sfd
.stream
);
163 r
->process_done
= true;
165 relay_close_if_done(r
);
168 void uh_relay_kill(struct client
*cl
, struct relay
*r
)
170 struct ustream
*us
= &r
->sfd
.stream
;
172 kill(r
->proc
.pid
, SIGKILL
);
174 ustream_state_change(us
);
177 void uh_relay_open(struct client
*cl
, struct relay
*r
, int fd
, int pid
)
179 struct ustream
*us
= &r
->sfd
.stream
;
182 us
->notify_read
= relay_read_cb
;
183 us
->notify_state
= relay_state_cb
;
184 us
->string_data
= true;
185 ustream_fd_init(&r
->sfd
, fd
);
188 r
->proc
.cb
= relay_proc_cb
;
189 uloop_process_add(&r
->proc
);