static int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) { http2_session_data *session_data = (http2_session_data*)user_data; http2_stream_data *stream_data; size_t i; const char PATH[] = ":path"; switch(frame->hd.type) { case NGHTTP2_HEADERS: if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) { break; } stream_data = create_http2_stream_data(session_data, frame->hd.stream_id); nghttp2_session_set_stream_user_data(session, frame->hd.stream_id, stream_data); for(i = 0; i < frame->headers.nvlen; ++i) { nghttp2_nv *nv = &frame->headers.nva[i]; if(nv->namelen == sizeof(PATH) - 1 && memcmp(PATH, nv->name, nv->namelen) == 0) { size_t j; for(j = 0; j < nv->valuelen && nv->value[j] != '?'; ++j); stream_data->request_path = percent_decode(nv->value, j); break; } } break; default: break; } return 0; }
static int on_begin_headers_callback(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) { http2_session_data *session_data = (http2_session_data *)user_data; http2_stream_data *stream_data; if (frame->hd.type != NGHTTP2_HEADERS || frame->headers.cat != NGHTTP2_HCAT_REQUEST) { return 0; } stream_data = create_http2_stream_data(session_data, frame->hd.stream_id); nghttp2_session_set_stream_user_data(session, frame->hd.stream_id, stream_data); return 0; }
/* Get resource denoted by the |uri|. The debug and error messages are printed in stderr, while the response body is printed in stdout. */ static void run(const char *uri) { struct http_parser_url u; char *host; uint16_t port; int rv; SSL_CTX *ssl_ctx; struct event_base *evbase; http2_session_data *session_data; /* Parse the |uri| and stores its components in |u| */ rv = http_parser_parse_url(uri, strlen(uri), 0, &u); if(rv != 0) { errx(1, "Could not parse URI %s", uri); } host = strndup(&uri[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len); if(!(u.field_set & (1 << UF_PORT))) { port = 443; } else { port = u.port; } ssl_ctx = create_ssl_ctx(); evbase = event_base_new(); session_data = create_http2_session_data(evbase); session_data->stream_data = create_http2_stream_data(uri, &u); initiate_connection(evbase, ssl_ctx, host, port, session_data); free(host); host = NULL; event_base_loop(evbase, 0); event_base_free(evbase); SSL_CTX_free(ssl_ctx); }