Path: blob/main/crypto/openssl/demos/http3/ossl-nghttp3-demo.c
39536 views
/*1* Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/8#include "ossl-nghttp3.h"9#include <openssl/err.h>1011static int done;1213static void make_nv(nghttp3_nv *nv, const char *name, const char *value)14{15nv->name = (uint8_t *)name;16nv->value = (uint8_t *)value;17nv->namelen = strlen(name);18nv->valuelen = strlen(value);19nv->flags = NGHTTP3_NV_FLAG_NONE;20}2122static int on_recv_header(nghttp3_conn *h3conn, int64_t stream_id,23int32_t token,24nghttp3_rcbuf *name, nghttp3_rcbuf *value,25uint8_t flags,26void *conn_user_data,27void *stream_user_data)28{29nghttp3_vec vname, vvalue;3031/* Received a single HTTP header. */32vname = nghttp3_rcbuf_get_buf(name);33vvalue = nghttp3_rcbuf_get_buf(value);3435fwrite(vname.base, vname.len, 1, stderr);36fprintf(stderr, ": ");37fwrite(vvalue.base, vvalue.len, 1, stderr);38fprintf(stderr, "\n");3940return 0;41}4243static int on_end_headers(nghttp3_conn *h3conn, int64_t stream_id,44int fin,45void *conn_user_data, void *stream_user_data)46{47fprintf(stderr, "\n");48return 0;49}5051static int on_recv_data(nghttp3_conn *h3conn, int64_t stream_id,52const uint8_t *data, size_t datalen,53void *conn_user_data, void *stream_user_data)54{55size_t wr;5657/* HTTP response body data - write it to stdout. */58while (datalen > 0) {59wr = fwrite(data, 1, datalen, stdout);60if (ferror(stdout))61return 1;6263data += wr;64datalen -= wr;65}6667return 0;68}6970static int on_end_stream(nghttp3_conn *h3conn, int64_t stream_id,71void *conn_user_data, void *stream_user_data)72{73/* HTTP transaction is done - set done flag so that we stop looping. */74done = 1;75return 0;76}7778int main(int argc, char **argv)79{80int ret = 1;81SSL_CTX *ctx = NULL;82OSSL_DEMO_H3_CONN *conn = NULL;83nghttp3_nv nva[16];84nghttp3_callbacks callbacks = {0};85size_t num_nv = 0;86const char *addr;8788/* Check arguments. */89if (argc < 2) {90fprintf(stderr, "usage: %s <host:port>\n", argv[0]);91goto err;92}9394addr = argv[1];9596/* Setup SSL_CTX. */97if ((ctx = SSL_CTX_new(OSSL_QUIC_client_method())) == NULL)98goto err;99100SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);101102if (SSL_CTX_set_default_verify_paths(ctx) == 0)103goto err;104105/* Setup callbacks. */106callbacks.recv_header = on_recv_header;107callbacks.end_headers = on_end_headers;108callbacks.recv_data = on_recv_data;109callbacks.end_stream = on_end_stream;110111/* Create connection. */112if ((conn = OSSL_DEMO_H3_CONN_new_for_addr(ctx, addr, &callbacks,113NULL, NULL)) == NULL) {114ERR_raise_data(ERR_LIB_USER, ERR_R_OPERATION_FAIL,115"cannot create HTTP/3 connection");116goto err;117}118119/* Build HTTP headers. */120make_nv(&nva[num_nv++], ":method", "GET");121make_nv(&nva[num_nv++], ":scheme", "https");122make_nv(&nva[num_nv++], ":authority", addr);123make_nv(&nva[num_nv++], ":path", "/");124make_nv(&nva[num_nv++], "user-agent", "OpenSSL-Demo/nghttp3");125126/* Submit request. */127if (!OSSL_DEMO_H3_CONN_submit_request(conn, nva, num_nv, NULL, NULL)) {128ERR_raise_data(ERR_LIB_USER, ERR_R_OPERATION_FAIL,129"cannot submit HTTP/3 request");130goto err;131}132133/* Wait for request to complete. */134while (!done)135if (!OSSL_DEMO_H3_CONN_handle_events(conn)) {136ERR_raise_data(ERR_LIB_USER, ERR_R_OPERATION_FAIL,137"cannot handle events");138goto err;139}140141ret = 0;142err:143if (ret != 0)144ERR_print_errors_fp(stderr);145146OSSL_DEMO_H3_CONN_free(conn);147SSL_CTX_free(ctx);148return ret;149}150151152