2 * uhttpd - Tiny single-threaded httpd
4 * Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
5 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
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
);
133 uh_chunk_write(cl
, buf
, len
);
134 ustream_consume(s
, len
);
137 static void relay_close_if_done(struct relay
*r
)
139 struct ustream
*s
= &r
->sfd
.stream
;
141 if (!s
->eof
|| ustream_pending_data(s
, false))
144 uh_relay_close(r
, r
->ret
);
147 static void relay_state_cb(struct ustream
*s
)
149 struct relay
*r
= container_of(s
, struct relay
, sfd
.stream
);
152 relay_close_if_done(r
);
155 static void relay_proc_cb(struct uloop_process
*proc
, int ret
)
157 struct relay
*r
= container_of(proc
, struct relay
, proc
);
159 r
->process_done
= true;
161 relay_close_if_done(r
);
164 void uh_relay_open(struct client
*cl
, struct relay
*r
, int fd
, int pid
)
166 struct ustream
*us
= &r
->sfd
.stream
;
169 us
->notify_read
= relay_read_cb
;
170 us
->notify_state
= relay_state_cb
;
171 us
->string_data
= true;
172 ustream_fd_init(&r
->sfd
, fd
);
175 r
->proc
.cb
= relay_proc_cb
;
176 uloop_process_add(&r
->proc
);