• Home
  • Raw
  • Download

Lines Matching +full:- +full:- +full:with +full:- +full:nghttp2

21  * SPDX-License-Identifier: curl
29 #include <nghttp2/nghttp2.h>
42 #include "cf-h2-proxy.h"
90 ts->state = H2_TUNNEL_INIT; in tunnel_stream_init()
91 ts->stream_id = -1; in tunnel_stream_init()
92 Curl_bufq_init2(&ts->recvbuf, PROXY_H2_CHUNK_SIZE, H2_TUNNEL_RECV_CHUNKS, in tunnel_stream_init()
94 Curl_bufq_init(&ts->sendbuf, PROXY_H2_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS); in tunnel_stream_init()
100 ts->authority = /* host:port with IPv6 support */ in tunnel_stream_init()
103 if(!ts->authority) in tunnel_stream_init()
111 Curl_http_resp_free(ts->resp); in tunnel_stream_clear()
112 Curl_bufq_free(&ts->recvbuf); in tunnel_stream_clear()
113 Curl_bufq_free(&ts->sendbuf); in tunnel_stream_clear()
114 Curl_safefree(ts->authority); in tunnel_stream_clear()
116 ts->state = H2_TUNNEL_INIT; in tunnel_stream_clear()
126 if(ts->state == new_state) in h2_tunnel_go_state()
129 switch(ts->state) { in h2_tunnel_go_state()
131 data->req.ignorebody = FALSE; in h2_tunnel_go_state()
139 CURL_TRC_CF(data, cf, "[%d] new tunnel state 'init'", ts->stream_id); in h2_tunnel_go_state()
144 CURL_TRC_CF(data, cf, "[%d] new tunnel state 'connect'", ts->stream_id); in h2_tunnel_go_state()
145 ts->state = H2_TUNNEL_CONNECT; in h2_tunnel_go_state()
149 CURL_TRC_CF(data, cf, "[%d] new tunnel state 'response'", ts->stream_id); in h2_tunnel_go_state()
150 ts->state = H2_TUNNEL_RESPONSE; in h2_tunnel_go_state()
155 ts->stream_id); in h2_tunnel_go_state()
157 data->state.authproxy.done = TRUE; in h2_tunnel_go_state()
158 data->state.authproxy.multipass = FALSE; in h2_tunnel_go_state()
162 CURL_TRC_CF(data, cf, "[%d] new tunnel state 'failed'", ts->stream_id); in h2_tunnel_go_state()
163 ts->state = new_state; in h2_tunnel_go_state()
164 /* If a proxy-authorization header was used for the proxy, then we should in h2_tunnel_go_state()
167 Curl_safefree(data->state.aptr.proxyuserpwd); in h2_tunnel_go_state()
192 ((struct cf_h2_proxy_ctx *)(cf)->ctx)->call_data
196 struct cf_call_data save = ctx->call_data; in cf_h2_proxy_ctx_clear()
198 if(ctx->h2) { in cf_h2_proxy_ctx_clear()
199 nghttp2_session_del(ctx->h2); in cf_h2_proxy_ctx_clear()
201 Curl_bufq_free(&ctx->inbufq); in cf_h2_proxy_ctx_clear()
202 Curl_bufq_free(&ctx->outbufq); in cf_h2_proxy_ctx_clear()
203 tunnel_stream_clear(&ctx->tunnel); in cf_h2_proxy_ctx_clear()
205 ctx->call_data = save; in cf_h2_proxy_ctx_clear()
220 struct cf_h2_proxy_ctx *ctx = cf->ctx; in drain_tunnel()
225 if(!tunnel->closed && !tunnel->reset && in drain_tunnel()
226 !Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) in drain_tunnel()
228 if(data->state.select_bits != bits) { in drain_tunnel()
230 tunnel->stream_id, bits); in drain_tunnel()
231 data->state.select_bits = bits; in drain_tunnel()
245 nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err); in proxy_nw_in_reader()
246 CURL_TRC_CF(data, cf, "[0] nw_in_reader(len=%zu) -> %zd, %d", in proxy_nw_in_reader()
264 nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, in proxy_h2_nw_out_writer()
266 CURL_TRC_CF(data, cf, "[0] nw_out_writer(len=%zu) -> %zd, %d", in proxy_h2_nw_out_writer()
278 struct cf_h2_proxy_ctx *ctx = cf->ctx; in proxy_h2_client_new()
289 /* with 1.50.0 */ in proxy_h2_client_new()
294 rc = nghttp2_session_client_new3(&ctx->h2, cbs, cf, o, &mem); in proxy_h2_client_new()
329 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_ctx_init()
334 DEBUGASSERT(!ctx->h2); in cf_h2_proxy_ctx_init()
335 memset(&ctx->tunnel, 0, sizeof(ctx->tunnel)); in cf_h2_proxy_ctx_init()
337 Curl_bufq_init(&ctx->inbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_RECV_CHUNKS); in cf_h2_proxy_ctx_init()
338 Curl_bufq_init(&ctx->outbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_SEND_CHUNKS); in cf_h2_proxy_ctx_init()
340 if(tunnel_stream_init(cf, &ctx->tunnel)) in cf_h2_proxy_ctx_init()
345 failf(data, "Couldn't initialize nghttp2 callbacks"); in cf_h2_proxy_ctx_init()
362 /* The nghttp2 session is not yet setup, do it */ in cf_h2_proxy_ctx_init()
365 failf(data, "Couldn't initialize nghttp2"); in cf_h2_proxy_ctx_init()
373 iv[0].value = Curl_multi_max_concurrent_streams(data->multi); in cf_h2_proxy_ctx_init()
378 rc = nghttp2_submit_settings(ctx->h2, NGHTTP2_FLAG_NONE, iv, 3); in cf_h2_proxy_ctx_init()
387 rc = nghttp2_session_set_local_window_size(ctx->h2, NGHTTP2_FLAG_NONE, 0, in cf_h2_proxy_ctx_init()
403 CURL_TRC_CF(data, cf, "[0] init proxy ctx -> %d", result); in cf_h2_proxy_ctx_init()
409 return !nghttp2_session_want_read(ctx->h2) && in proxy_h2_should_close_session()
410 !nghttp2_session_want_write(ctx->h2); in proxy_h2_should_close_session()
416 struct cf_h2_proxy_ctx *ctx = cf->ctx; in proxy_h2_nw_out_flush()
421 if(Curl_bufq_is_empty(&ctx->outbufq)) in proxy_h2_nw_out_flush()
424 nwritten = Curl_bufq_pass(&ctx->outbufq, proxy_h2_nw_out_writer, cf, in proxy_h2_nw_out_flush()
428 CURL_TRC_CF(data, cf, "[0] flush nw send buffer(%zu) -> EAGAIN", in proxy_h2_nw_out_flush()
429 Curl_bufq_len(&ctx->outbufq)); in proxy_h2_nw_out_flush()
430 ctx->nw_out_blocked = 1; in proxy_h2_nw_out_flush()
435 return Curl_bufq_is_empty(&ctx->outbufq) ? CURLE_OK : CURLE_AGAIN; in proxy_h2_nw_out_flush()
440 * This function returns 0 if it succeeds, or -1 and error code will
447 struct cf_h2_proxy_ctx *ctx = cf->ctx; in proxy_h2_process_pending_input()
452 while(Curl_bufq_peek(&ctx->inbufq, &buf, &blen)) { in proxy_h2_process_pending_input()
454 rv = nghttp2_session_mem_recv(ctx->h2, (const uint8_t *)buf, blen); in proxy_h2_process_pending_input()
455 CURL_TRC_CF(data, cf, "[0] %zu bytes to nghttp2 -> %zd", blen, rv); in proxy_h2_process_pending_input()
461 return -1; in proxy_h2_process_pending_input()
463 Curl_bufq_skip(&ctx->inbufq, (size_t)rv); in proxy_h2_process_pending_input()
464 if(Curl_bufq_is_empty(&ctx->inbufq)) { in proxy_h2_process_pending_input()
470 "in connection buffer", Curl_bufq_len(&ctx->inbufq)); in proxy_h2_process_pending_input()
480 struct cf_h2_proxy_ctx *ctx = cf->ctx; in proxy_h2_progress_ingress()
485 if(!Curl_bufq_is_empty(&ctx->inbufq)) { in proxy_h2_progress_ingress()
487 Curl_bufq_len(&ctx->inbufq)); in proxy_h2_progress_ingress()
494 while(!ctx->conn_closed && /* not closed the connection */ in proxy_h2_progress_ingress()
495 !ctx->tunnel.closed && /* nor the tunnel */ in proxy_h2_progress_ingress()
496 Curl_bufq_is_empty(&ctx->inbufq) && /* and we consumed our input */ in proxy_h2_progress_ingress()
497 !Curl_bufq_is_full(&ctx->tunnel.recvbuf)) { in proxy_h2_progress_ingress()
499 nread = Curl_bufq_slurp(&ctx->inbufq, proxy_nw_in_reader, cf, &result); in proxy_h2_progress_ingress()
500 CURL_TRC_CF(data, cf, "[0] read %zu bytes nw data -> %zd, %d", in proxy_h2_progress_ingress()
501 Curl_bufq_len(&ctx->inbufq), nread, result); in proxy_h2_progress_ingress()
510 ctx->conn_closed = TRUE; in proxy_h2_progress_ingress()
518 if(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) { in proxy_h2_progress_ingress()
519 connclose(cf->conn, "GOAWAY received"); in proxy_h2_progress_ingress()
528 struct cf_h2_proxy_ctx *ctx = cf->ctx; in proxy_h2_progress_egress()
531 ctx->nw_out_blocked = 0; in proxy_h2_progress_egress()
532 while(!rv && !ctx->nw_out_blocked && nghttp2_session_want_write(ctx->h2)) in proxy_h2_progress_egress()
533 rv = nghttp2_session_send(ctx->h2); in proxy_h2_progress_egress()
548 struct cf_h2_proxy_ctx *ctx = cf->ctx; in on_session_send()
557 nwritten = Curl_bufq_write_pass(&ctx->outbufq, buf, blen, in on_session_send()
577 switch(frame->hd.type) { in proxy_h2_fr_print()
581 (int)frame->hd.length, in proxy_h2_fr_print()
582 !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM), in proxy_h2_fr_print()
583 (int)frame->data.padlen); in proxy_h2_fr_print()
588 (int)frame->hd.length, in proxy_h2_fr_print()
589 !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS), in proxy_h2_fr_print()
590 !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)); in proxy_h2_fr_print()
595 (int)frame->hd.length, frame->hd.flags); in proxy_h2_fr_print()
600 (int)frame->hd.length, frame->hd.flags, in proxy_h2_fr_print()
601 frame->rst_stream.error_code); in proxy_h2_fr_print()
604 if(frame->hd.flags & NGHTTP2_FLAG_ACK) { in proxy_h2_fr_print()
608 "FRAME[SETTINGS, len=%d]", (int)frame->hd.length); in proxy_h2_fr_print()
613 (int)frame->hd.length, in proxy_h2_fr_print()
614 !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS)); in proxy_h2_fr_print()
618 (int)frame->hd.length, in proxy_h2_fr_print()
619 frame->hd.flags & NGHTTP2_FLAG_ACK); in proxy_h2_fr_print()
623 size_t len = (frame->goaway.opaque_data_len < s_len) ? in proxy_h2_fr_print()
624 frame->goaway.opaque_data_len : s_len-1; in proxy_h2_fr_print()
626 memcpy(scratch, frame->goaway.opaque_data, len); in proxy_h2_fr_print()
629 "last_stream=%d]", frame->goaway.error_code, in proxy_h2_fr_print()
630 scratch, frame->goaway.last_stream_id); in proxy_h2_fr_print()
635 frame->window_update.window_size_increment); in proxy_h2_fr_print()
639 frame->hd.type, (int)frame->hd.length, in proxy_h2_fr_print()
640 frame->hd.flags); in proxy_h2_fr_print()
656 len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1); in proxy_h2_on_frame_send()
658 CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer); in proxy_h2_on_frame_send()
669 struct cf_h2_proxy_ctx *ctx = cf->ctx; in proxy_h2_on_frame_recv()
671 int32_t stream_id = frame->hd.stream_id; in proxy_h2_on_frame_recv()
679 len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1); in proxy_h2_on_frame_recv()
681 CURL_TRC_CF(data, cf, "[%d] <- %s",frame->hd.stream_id, buffer); in proxy_h2_on_frame_recv()
686 /* stream ID zero is for connection-oriented stuff */ in proxy_h2_on_frame_recv()
688 switch(frame->hd.type) { in proxy_h2_on_frame_recv()
696 drain_tunnel(cf, data, &ctx->tunnel); in proxy_h2_on_frame_recv()
700 ctx->rcvd_goaway = TRUE; in proxy_h2_on_frame_recv()
708 if(stream_id != ctx->tunnel.stream_id) { in proxy_h2_on_frame_recv()
713 switch(frame->hd.type) { in proxy_h2_on_frame_recv()
715 /* nghttp2 guarantees that :status is received, and we store it to in proxy_h2_on_frame_recv()
716 stream->status_code. Fuzzing has proven this can still be reached in proxy_h2_on_frame_recv()
718 if(!ctx->tunnel.resp) in proxy_h2_on_frame_recv()
722 stream_id, ctx->tunnel.resp->status); in proxy_h2_on_frame_recv()
723 if(!ctx->tunnel.has_final_response) { in proxy_h2_on_frame_recv()
724 if(ctx->tunnel.resp->status / 100 != 1) { in proxy_h2_on_frame_recv()
725 ctx->tunnel.has_final_response = TRUE; in proxy_h2_on_frame_recv()
731 drain_tunnel(cf, data, &ctx->tunnel); in proxy_h2_on_frame_recv()
748 struct cf_h2_proxy_ctx *ctx = cf->ctx; in proxy_h2_on_header()
750 int32_t stream_id = frame->hd.stream_id; in proxy_h2_on_header()
757 if(stream_id != ctx->tunnel.stream_id) { in proxy_h2_on_header()
758 CURL_TRC_CF(data, cf, "[%d] header for non-tunnel stream: " in proxy_h2_on_header()
764 if(frame->hd.type == NGHTTP2_PUSH_PROMISE) in proxy_h2_on_header()
767 if(ctx->tunnel.has_final_response) { in proxy_h2_on_header()
768 /* we do not do anything with trailers for tunnel streams */ in proxy_h2_on_header()
772 if(namelen == sizeof(HTTP_PSEUDO_STATUS) - 1 && in proxy_h2_on_header()
786 resp->prev = ctx->tunnel.resp; in proxy_h2_on_header()
787 ctx->tunnel.resp = resp; in proxy_h2_on_header()
789 stream_id, ctx->tunnel.resp->status); in proxy_h2_on_header()
793 if(!ctx->tunnel.resp) in proxy_h2_on_header()
796 result = Curl_dynhds_add(&ctx->tunnel.resp->headers, in proxy_h2_on_header()
816 struct cf_h2_proxy_ctx *ctx = cf->ctx; in tunnel_send_callback()
832 DEBUGASSERT(ts == &ctx->tunnel); in tunnel_send_callback()
834 nread = Curl_bufq_read(&ts->sendbuf, buf, length, &result); in tunnel_send_callback()
840 if(ts->closed && Curl_bufq_is_empty(&ts->sendbuf)) in tunnel_send_callback()
843 CURL_TRC_CF(data, cf, "[%d] tunnel_send_callback -> %zd", in tunnel_send_callback()
844 ts->stream_id, nread); in tunnel_send_callback()
853 struct cf_h2_proxy_ctx *ctx = cf->ctx; in tunnel_recv_callback()
861 if(stream_id != ctx->tunnel.stream_id) in tunnel_recv_callback()
864 nwritten = Curl_bufq_write(&ctx->tunnel.recvbuf, mem, len, &result); in tunnel_recv_callback()
881 struct cf_h2_proxy_ctx *ctx = cf->ctx; in proxy_h2_on_stream_close()
887 if(stream_id != ctx->tunnel.stream_id) in proxy_h2_on_stream_close()
892 ctx->tunnel.closed = TRUE; in proxy_h2_on_stream_close()
893 ctx->tunnel.error = error_code; in proxy_h2_on_stream_close()
910 int32_t stream_id = -1; in proxy_h2_submit()
958 struct cf_h2_proxy_ctx *ctx = cf->ctx; in submit_CONNECT()
969 infof(data, "Establish HTTP/2 proxy tunnel to %s", req->authority); in submit_CONNECT()
971 result = proxy_h2_submit(&ts->stream_id, cf, data, ctx->h2, req, in submit_CONNECT()
975 ts->stream_id, nghttp2_strerror(ts->stream_id)); in submit_CONNECT()
994 DEBUGASSERT(ts->resp); in inspect_response()
995 if(ts->resp->status/100 == 2) { in inspect_response()
996 infof(data, "CONNECT tunnel established, response %d", ts->resp->status); in inspect_response()
1001 if(ts->resp->status == 401) { in inspect_response()
1002 auth_reply = Curl_dynhds_cget(&ts->resp->headers, "WWW-Authenticate"); in inspect_response()
1004 else if(ts->resp->status == 407) { in inspect_response()
1005 auth_reply = Curl_dynhds_cget(&ts->resp->headers, "Proxy-Authenticate"); in inspect_response()
1010 auth_reply->value); in inspect_response()
1011 result = Curl_http_input_auth(data, ts->resp->status == 407, in inspect_response()
1012 auth_reply->value); in inspect_response()
1015 if(data->req.newurl) { in inspect_response()
1017 Curl_safefree(data->req.newurl); in inspect_response()
1031 struct cf_h2_proxy_ctx *ctx = cf->ctx; in H2_CONNECT()
1035 DEBUGASSERT(ts->authority); in H2_CONNECT()
1037 switch(ts->state) { in H2_CONNECT()
1040 CURL_TRC_CF(data, cf, "[0] CONNECT start for %s", ts->authority); in H2_CONNECT()
1057 if(ts->has_final_response) { in H2_CONNECT()
1067 DEBUGASSERT(ts->has_final_response); in H2_CONNECT()
1083 } while(ts->state == H2_TUNNEL_INIT); in H2_CONNECT()
1086 if((result && (result != CURLE_AGAIN)) || ctx->tunnel.closed) in H2_CONNECT()
1095 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_connect()
1099 struct tunnel_stream *ts = &ctx->tunnel; in cf_h2_proxy_connect()
1101 if(cf->connected) { in cf_h2_proxy_connect()
1107 if(!cf->next->connected) { in cf_h2_proxy_connect()
1108 result = Curl_conn_cf_connect(cf->next, data, blocking, done); in cf_h2_proxy_connect()
1116 if(!ctx->h2) { in cf_h2_proxy_connect()
1121 DEBUGASSERT(ts->authority); in cf_h2_proxy_connect()
1136 *done = (result == CURLE_OK) && (ts->state == H2_TUNNEL_ESTABLISHED); in cf_h2_proxy_connect()
1138 cf->connected = TRUE; in cf_h2_proxy_connect()
1140 Curl_req_soft_reset(&data->req, data); in cf_h2_proxy_connect()
1149 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_close()
1158 if(cf->next) in cf_h2_proxy_close()
1159 cf->next->cft->do_close(cf->next, data); in cf_h2_proxy_close()
1165 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_destroy()
1170 cf->ctx = NULL; in cf_h2_proxy_destroy()
1177 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_shutdown()
1182 if(!cf->connected || !ctx->h2 || cf->shutdown || ctx->conn_closed) { in cf_h2_proxy_shutdown()
1189 if(!ctx->sent_goaway) { in cf_h2_proxy_shutdown()
1190 rv = nghttp2_submit_goaway(ctx->h2, NGHTTP2_FLAG_NONE, in cf_h2_proxy_shutdown()
1200 ctx->sent_goaway = TRUE; in cf_h2_proxy_shutdown()
1202 /* GOAWAY submitted, process egress and ingress until nghttp2 is done. */ in cf_h2_proxy_shutdown()
1204 if(nghttp2_session_want_write(ctx->h2)) in cf_h2_proxy_shutdown()
1206 if(!result && nghttp2_session_want_read(ctx->h2)) in cf_h2_proxy_shutdown()
1209 *done = (ctx->conn_closed || in cf_h2_proxy_shutdown()
1210 (!result && !nghttp2_session_want_write(ctx->h2) && in cf_h2_proxy_shutdown()
1211 !nghttp2_session_want_read(ctx->h2))); in cf_h2_proxy_shutdown()
1214 cf->shutdown = (result || *done); in cf_h2_proxy_shutdown()
1221 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_data_pending()
1222 if((ctx && !Curl_bufq_is_empty(&ctx->inbufq)) || in cf_h2_proxy_data_pending()
1223 (ctx && ctx->tunnel.state == H2_TUNNEL_ESTABLISHED && in cf_h2_proxy_data_pending()
1224 !Curl_bufq_is_empty(&ctx->tunnel.recvbuf))) in cf_h2_proxy_data_pending()
1226 return cf->next ? cf->next->cft->has_data_pending(cf->next, data) : FALSE; in cf_h2_proxy_data_pending()
1233 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_adjust_pollset()
1238 if(!cf->connected && ctx->h2) { in cf_h2_proxy_adjust_pollset()
1239 want_send = nghttp2_session_want_write(ctx->h2) || in cf_h2_proxy_adjust_pollset()
1240 !Curl_bufq_is_empty(&ctx->outbufq) || in cf_h2_proxy_adjust_pollset()
1241 !Curl_bufq_is_empty(&ctx->tunnel.sendbuf); in cf_h2_proxy_adjust_pollset()
1242 want_recv = nghttp2_session_want_read(ctx->h2); in cf_h2_proxy_adjust_pollset()
1247 if(ctx->h2 && (want_recv || want_send)) { in cf_h2_proxy_adjust_pollset()
1251 c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2); in cf_h2_proxy_adjust_pollset()
1252 s_exhaust = ctx->tunnel.stream_id >= 0 && in cf_h2_proxy_adjust_pollset()
1254 ctx->h2, ctx->tunnel.stream_id); in cf_h2_proxy_adjust_pollset()
1257 (!c_exhaust && nghttp2_session_want_write(ctx->h2)) || in cf_h2_proxy_adjust_pollset()
1258 !Curl_bufq_is_empty(&ctx->outbufq) || in cf_h2_proxy_adjust_pollset()
1259 !Curl_bufq_is_empty(&ctx->tunnel.sendbuf); in cf_h2_proxy_adjust_pollset()
1266 else if(ctx->sent_goaway && !cf->shutdown) { in cf_h2_proxy_adjust_pollset()
1269 want_send = nghttp2_session_want_write(ctx->h2) || in cf_h2_proxy_adjust_pollset()
1270 !Curl_bufq_is_empty(&ctx->outbufq) || in cf_h2_proxy_adjust_pollset()
1271 !Curl_bufq_is_empty(&ctx->tunnel.sendbuf); in cf_h2_proxy_adjust_pollset()
1272 want_recv = nghttp2_session_want_read(ctx->h2); in cf_h2_proxy_adjust_pollset()
1284 struct cf_h2_proxy_ctx *ctx = cf->ctx; in h2_handle_tunnel_close()
1287 if(ctx->tunnel.error == NGHTTP2_REFUSED_STREAM) { in h2_handle_tunnel_close()
1289 "connection", ctx->tunnel.stream_id); in h2_handle_tunnel_close()
1290 connclose(cf->conn, "REFUSED_STREAM"); /* do not use this anymore */ in h2_handle_tunnel_close()
1292 return -1; in h2_handle_tunnel_close()
1294 else if(ctx->tunnel.error != NGHTTP2_NO_ERROR) { in h2_handle_tunnel_close()
1296 ctx->tunnel.stream_id, nghttp2_http2_strerror(ctx->tunnel.error), in h2_handle_tunnel_close()
1297 ctx->tunnel.error); in h2_handle_tunnel_close()
1299 return -1; in h2_handle_tunnel_close()
1301 else if(ctx->tunnel.reset) { in h2_handle_tunnel_close()
1302 failf(data, "HTTP/2 stream %u was reset", ctx->tunnel.stream_id); in h2_handle_tunnel_close()
1304 return -1; in h2_handle_tunnel_close()
1309 CURL_TRC_CF(data, cf, "[%d] handle_tunnel_close -> %zd, %d", in h2_handle_tunnel_close()
1310 ctx->tunnel.stream_id, rv, *err); in h2_handle_tunnel_close()
1317 struct cf_h2_proxy_ctx *ctx = cf->ctx; in tunnel_recv()
1318 ssize_t nread = -1; in tunnel_recv()
1321 if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf)) { in tunnel_recv()
1322 nread = Curl_bufq_read(&ctx->tunnel.recvbuf, in tunnel_recv()
1330 if(ctx->tunnel.closed) { in tunnel_recv()
1333 else if(ctx->tunnel.reset || in tunnel_recv()
1334 (ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) || in tunnel_recv()
1335 (ctx->rcvd_goaway && in tunnel_recv()
1336 ctx->last_stream_id < ctx->tunnel.stream_id)) { in tunnel_recv()
1338 nread = -1; in tunnel_recv()
1343 nread = -1; in tunnel_recv()
1347 CURL_TRC_CF(data, cf, "[%d] tunnel_recv(len=%zu) -> %zd, %d", in tunnel_recv()
1348 ctx->tunnel.stream_id, len, nread, *err); in tunnel_recv()
1356 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_recv()
1357 ssize_t nread = -1; in cf_h2_proxy_recv()
1361 if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) { in cf_h2_proxy_recv()
1363 return -1; in cf_h2_proxy_recv()
1367 if(Curl_bufq_is_empty(&ctx->tunnel.recvbuf)) { in cf_h2_proxy_recv()
1377 ctx->tunnel.stream_id, nread); in cf_h2_proxy_recv()
1378 nghttp2_session_consume(ctx->h2, ctx->tunnel.stream_id, (size_t)nread); in cf_h2_proxy_recv()
1384 nread = -1; in cf_h2_proxy_recv()
1388 if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf) && in cf_h2_proxy_recv()
1392 drain_tunnel(cf, data, &ctx->tunnel); in cf_h2_proxy_recv()
1394 CURL_TRC_CF(data, cf, "[%d] cf_recv(len=%zu) -> %zd %d", in cf_h2_proxy_recv()
1395 ctx->tunnel.stream_id, len, nread, *err); in cf_h2_proxy_recv()
1405 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_send()
1412 if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) { in cf_h2_proxy_send()
1414 return -1; in cf_h2_proxy_send()
1418 if(ctx->tunnel.closed) { in cf_h2_proxy_send()
1419 nwritten = -1; in cf_h2_proxy_send()
1424 nwritten = Curl_bufq_write(&ctx->tunnel.sendbuf, buf, len, err); in cf_h2_proxy_send()
1429 if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) { in cf_h2_proxy_send()
1431 rv = nghttp2_session_resume_data(ctx->h2, ctx->tunnel.stream_id); in cf_h2_proxy_send()
1434 nwritten = -1; in cf_h2_proxy_send()
1442 nwritten = -1; in cf_h2_proxy_send()
1446 /* Call the nghttp2 send loop and flush to write ALL buffered data, in cf_h2_proxy_send()
1451 nwritten = -1; in cf_h2_proxy_send()
1456 /* nghttp2 thinks this session is done. If the stream has not been in cf_h2_proxy_send()
1458 if(ctx->tunnel.closed) { in cf_h2_proxy_send()
1460 nwritten = -1; in cf_h2_proxy_send()
1465 nwritten = -1; in cf_h2_proxy_send()
1470 if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf) && in cf_h2_proxy_send()
1474 drain_tunnel(cf, data, &ctx->tunnel); in cf_h2_proxy_send()
1476 CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) -> %zd, %d, " in cf_h2_proxy_send()
1477 "h2 windows %d-%d (stream-conn), buffers %zu-%zu (stream-conn)", in cf_h2_proxy_send()
1478 ctx->tunnel.stream_id, len, nwritten, *err, in cf_h2_proxy_send()
1480 ctx->h2, ctx->tunnel.stream_id), in cf_h2_proxy_send()
1481 nghttp2_session_get_remote_window_size(ctx->h2), in cf_h2_proxy_send()
1482 Curl_bufq_len(&ctx->tunnel.sendbuf), in cf_h2_proxy_send()
1483 Curl_bufq_len(&ctx->outbufq)); in cf_h2_proxy_send()
1491 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_flush()
1496 if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) { in cf_h2_proxy_flush()
1498 int rv = nghttp2_session_resume_data(ctx->h2, ctx->tunnel.stream_id); in cf_h2_proxy_flush()
1508 CURL_TRC_CF(data, cf, "[%d] flush -> %d, " in cf_h2_proxy_flush()
1509 "h2 windows %d-%d (stream-conn), buffers %zu-%zu (stream-conn)", in cf_h2_proxy_flush()
1510 ctx->tunnel.stream_id, result, in cf_h2_proxy_flush()
1512 ctx->h2, ctx->tunnel.stream_id), in cf_h2_proxy_flush()
1513 nghttp2_session_get_remote_window_size(ctx->h2), in cf_h2_proxy_flush()
1514 Curl_bufq_len(&ctx->tunnel.sendbuf), in cf_h2_proxy_flush()
1515 Curl_bufq_len(&ctx->outbufq)); in cf_h2_proxy_flush()
1524 struct cf_h2_proxy_ctx *ctx = cf->ctx; in proxy_h2_connisalive()
1528 if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending)) in proxy_h2_connisalive()
1536 ssize_t nread = -1; in proxy_h2_connisalive()
1539 nread = Curl_bufq_slurp(&ctx->inbufq, proxy_nw_in_reader, cf, &result); in proxy_h2_connisalive()
1540 if(nread != -1) { in proxy_h2_connisalive()
1561 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_is_alive()
1566 result = (ctx && ctx->h2 && proxy_h2_connisalive(cf, data, input_pending)); in cf_h2_proxy_is_alive()
1567 CURL_TRC_CF(data, cf, "[0] conn alive -> %d, input_pending=%d", in cf_h2_proxy_is_alive()
1577 struct cf_h2_proxy_ctx *ctx = cf->ctx; in cf_h2_proxy_query()
1581 if(!Curl_bufq_is_empty(&ctx->outbufq) || in cf_h2_proxy_query()
1582 !Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) { in cf_h2_proxy_query()
1592 return cf->next ? in cf_h2_proxy_query()
1593 cf->next->cft->query(cf->next, data, query, pres1, pres2) : in cf_h2_proxy_query()
1620 "H2-PROXY",