Compare commits

..

10 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
7e926d50dd Minor improvements to script: fix regex and add clarifying comments
Co-authored-by: tatsuhiro-t <404610+tatsuhiro-t@users.noreply.github.com>
2025-11-01 00:32:55 +00:00
copilot-swe-agent[bot]
29a014a418 Address code review feedback - clarify limitations and fix exception handling
Co-authored-by: tatsuhiro-t <404610+tatsuhiro-t@users.noreply.github.com>
2025-11-01 00:29:43 +00:00
copilot-swe-agent[bot]
4af1e4cf55 Add reusable script for finding unused symbols
Co-authored-by: tatsuhiro-t <404610+tatsuhiro-t@users.noreply.github.com>
2025-11-01 00:25:00 +00:00
copilot-swe-agent[bot]
4334ded205 Add comprehensive unused symbols analysis report
Co-authored-by: tatsuhiro-t <404610+tatsuhiro-t@users.noreply.github.com>
2025-11-01 00:22:26 +00:00
copilot-swe-agent[bot]
a99e209b2e Initial plan 2025-11-01 00:06:01 +00:00
Tatsuhiro Tsujikawa
3fa6a6349c Merge pull request #2546 from nghttp2/dependabot/github_actions/actions/upload-artifact-5
build(deps): bump actions/upload-artifact from 4 to 5
2025-10-28 08:33:37 +09:00
dependabot[bot]
6c0fd9400d build(deps): bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 15:21:33 +00:00
Tatsuhiro Tsujikawa
de81da7621 Merge pull request #2545 from nghttp2/simplify-format-hex
src: Simplify format_hex and format_upper_hex
2025-10-27 18:53:39 +09:00
Tatsuhiro Tsujikawa
8593b1f46c src: Simplify format_hex and format_upper_hex
Ignore -Wsign-conversion warning to avoid an issue that is very hard
to workaround.
2025-10-27 18:20:03 +09:00
Tatsuhiro Tsujikawa
0e9d325dee Bump package version 2025-10-25 17:34:56 +09:00
17 changed files with 440 additions and 571 deletions

View File

@@ -24,7 +24,7 @@ jobs:
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
if: failure()
with:
name: artifacts

View File

@@ -24,12 +24,12 @@
cmake_minimum_required(VERSION 3.14)
# XXX using 1.8.90 instead of 1.9.0-DEV
project(nghttp2 VERSION 1.68.1 LANGUAGES C)
project(nghttp2 VERSION 1.68.90 LANGUAGES C)
# See versioning rule:
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
set(LT_CURRENT 43)
set(LT_REVISION 3)
set(LT_REVISION 2)
set(LT_AGE 29)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})

88
UNUSED_SYMBOLS.md Normal file
View File

@@ -0,0 +1,88 @@
# Unused Symbols Report
This document lists unused functions, macros, and enums found in the nghttp2 library.
**Analysis Date:** 2025-11-01
**Scope:** Private symbols in `lib/` directory (excluding public API in `lib/includes/nghttp2/`)
## Summary
- **Unused Functions:** 0
- **Unused Macros:** 3
- **Unused Enums:** 2
- **Total Unused Symbols:** 5
## Methodology
The analysis was performed by:
1. Parsing all source files (`.c` and `.h`) in the `lib/` directory
2. Extracting function definitions, macro definitions, and enum declarations
3. Excluding symbols defined in the public API (`lib/includes/nghttp2/nghttp2.h`)
4. Counting references to each symbol across the entire codebase (including `lib/`, `src/`, `examples/`, `tests/`)
5. Identifying symbols that appear only once (in their definition) or have no references beyond their definition
Note: All private functions that were initially detected as potentially unused were found to actually be in use, either:
- In conditional compilation paths (platform-specific code)
- As static helper functions called within the same file
- Through function pointers or callbacks
## Unused Private Macros (3)
| Macro Name | File Location | Description |
|-----------|---------------|-------------|
| `NGHTTP2_PRIORITY_MASK` | lib/nghttp2_frame.h | Mask for priority value, defined but never used |
| `NGHTTP2_PRI_GROUP_ID_MASK` | lib/nghttp2_frame.h | Mask for priority group ID, defined but never used |
| `NGHTTP2_SETTINGS_ID_MASK` | lib/nghttp2_frame.h | Mask for settings ID, defined but never used |
**Note:** The SFPARSE_STATE_* macros (`SFPARSE_STATE_DICT`, `SFPARSE_STATE_ITEM`, `SFPARSE_STATE_LIST`) were initially identified as unused, but they are actually used through token concatenation in macro expansions (e.g., `SFPARSE_STATE_##NAME`). They are not truly unused.
## Unused Private Enums (2)
| Enum Name | File Location | Description |
|-----------|---------------|-------------|
| `NGHTTP2_ERR_CREDENTIAL_PENDING` | lib/nghttp2_int.h | Error code (-101), defined but never referenced |
| `NGHTTP2_TYPEMASK_NONE` | lib/nghttp2_session.h | Type mask value (0), defined but never referenced |
## Notes
- All symbols listed are **private** (not part of the public API in `lib/includes/nghttp2/`)
- These symbols have only one reference (their definition) in the entire codebase
- All detected private functions were found to be in active use through various means (conditional compilation, static helpers, callbacks)
**Important Note:** This analysis uses simple pattern matching and may not detect all forms of indirect usage, particularly:
- Macro token concatenation (e.g., `##NAME` in macro expansions)
- Function pointers passed through complex call chains
- Symbols used in platform-specific conditional compilation
## Detailed Findings
### Macros
The 3 unused macros are frame header masks that appear to be leftover definitions from earlier versions or reserved for future use:
- **NGHTTP2_PRIORITY_MASK**: Mask for priority value
- **NGHTTP2_PRI_GROUP_ID_MASK**: Mask for priority group ID
- **NGHTTP2_SETTINGS_ID_MASK**: Mask for settings ID
### Enums
Both unused enum values appear to be reserved for specific features:
1. **NGHTTP2_ERR_CREDENTIAL_PENDING**: Error code -101, possibly reserved for future credential handling features
2. **NGHTTP2_TYPEMASK_NONE**: A zero-value type mask that may have been used historically but is no longer needed
## Recommendations
1. **Review each symbol** to determine if it should be removed or is kept for a specific reason (e.g., future use, compatibility)
2. **Consider adding comments** to explain why symbols are kept if they appear unused but serve a purpose
3. **Remove confirmed unused symbols** to reduce code complexity and maintenance burden
4. **Update documentation** if any symbols were intended for public use but are not actually exposed
## Re-running the Analysis
A Python script is provided to re-run this analysis:
```bash
python3 find_unused_symbols.py
```
This script can be used to verify that unused symbols have been removed or to check for new unused symbols in the future.

View File

@@ -25,7 +25,7 @@ dnl Do not change user variables!
dnl https://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
AC_PREREQ(2.61)
AC_INIT([nghttp2], [1.68.1], [t-tujikawa@users.sourceforge.net])
AC_INIT([nghttp2], [1.69.0-DEV], [t-tujikawa@users.sourceforge.net])
AC_CONFIG_AUX_DIR([.])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
@@ -45,7 +45,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl See versioning rule:
dnl https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 43)
AC_SUBST(LT_REVISION, 3)
AC_SUBST(LT_REVISION, 2)
AC_SUBST(LT_AGE, 29)
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "H2LOAD" "1" "Mar 18, 2026" "1.68.1" "nghttp2"
.TH "H2LOAD" "1" "Oct 25, 2025" "1.68.0" "nghttp2"
.SH NAME
h2load \- HTTP/2 benchmarking tool
.SH SYNOPSIS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "NGHTTP" "1" "Mar 18, 2026" "1.68.1" "nghttp2"
.TH "NGHTTP" "1" "Oct 25, 2025" "1.68.0" "nghttp2"
.SH NAME
nghttp \- HTTP/2 client
.SH SYNOPSIS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "NGHTTPD" "1" "Mar 18, 2026" "1.68.1" "nghttp2"
.TH "NGHTTPD" "1" "Oct 25, 2025" "1.68.0" "nghttp2"
.SH NAME
nghttpd \- HTTP/2 server
.SH SYNOPSIS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "NGHTTPX" "1" "Mar 18, 2026" "1.68.1" "nghttp2"
.TH "NGHTTPX" "1" "Oct 25, 2025" "1.68.0" "nghttp2"
.SH NAME
nghttpx \- HTTP/2 proxy
.SH SYNOPSIS

265
find_unused_symbols.py Executable file
View File

@@ -0,0 +1,265 @@
#!/usr/bin/env python3
"""
Find unused functions, macros, and enums in the nghttp2 library.
Excludes symbols defined in lib/includes/nghttp2/ (public API).
Usage:
python3 find_unused_symbols.py
This script analyzes the nghttp2 library source code to find private symbols
(functions, macros, enums) that are defined but never used. It excludes symbols
that are part of the public API.
"""
import os
import re
import sys
from pathlib import Path
def get_lib_files(lib_dir):
"""Get all .c and .h files in lib directory, excluding public headers."""
files = []
public_dir = os.path.join(lib_dir, 'includes', 'nghttp2')
for root, dirs, filenames in os.walk(lib_dir):
if os.path.abspath(root).startswith(os.path.abspath(public_dir)):
continue
for filename in filenames:
if filename.endswith(('.c', '.h')):
files.append(os.path.join(root, filename))
return files
def get_all_project_files(base_dir):
"""Get all source files in the entire project."""
files = []
for root, dirs, filenames in os.walk(base_dir):
if '.git' in root or 'build' in root:
continue
for filename in filenames:
if filename.endswith(('.c', '.h', '.cc', '.cpp')):
files.append(os.path.join(root, filename))
return files
def get_public_api_symbols(public_header):
"""Extract all symbols from the public API header."""
symbols = set()
if not os.path.exists(public_header):
return symbols
with open(public_header, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
# Remove comments
content = re.sub(r'/\*.*?\*/', '', content, flags=re.DOTALL)
content = re.sub(r'//.*?$', '', content, flags=re.MULTILINE)
# Extract all symbols that look like functions, types, macros, enums
for match in re.finditer(r'\b([a-zA-Z_][a-zA-Z0-9_]*)\b', content):
name = match.group(1)
if name.startswith('nghttp2_') or name.startswith('NGHTTP2_') or name.startswith('sfparse_'):
symbols.add(name)
return symbols
def extract_definitions(filepath):
"""Extract function, macro, and enum definitions from a file."""
functions = {}
macros = {}
enums = {}
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
no_comments = re.sub(r'/\*.*?\*/', '', content, flags=re.DOTALL)
no_comments = re.sub(r'//.*?$', '', no_comments, flags=re.MULTILINE)
# Extract function definitions
func_pattern = r'\b(?:static\s+)?(?:inline\s+|STIN\s+)?(?:const\s+)?([a-zA-Z_][a-zA-Z0-9_*\s]+)\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\([^)]*\)\s*\{'
for match in re.finditer(func_pattern, no_comments):
func_name = match.group(2).strip()
if func_name not in ['if', 'for', 'while', 'switch', 'main']:
functions[func_name] = filepath
# Extract macros (uppercase convention only - lowercase macros not detected)
# This is intentional to focus on constant-like macros and avoid false positives
macro_pattern = r'^\s*#define\s+([A-Z_][A-Z0-9_]*)'
for match in re.finditer(macro_pattern, content, re.MULTILINE):
macro_name = match.group(1)
if not (macro_name.endswith('_H') or macro_name.endswith('_H_')):
macros[macro_name] = filepath
# Extract enum type names and members
enum_pattern = r'(?:typedef\s+)?enum\s+([a-zA-Z_][a-zA-Z0-9_]*)'
for match in re.finditer(enum_pattern, no_comments):
enums[match.group(1)] = filepath
enum_member_pattern = r'(?:typedef\s+)?enum\s*(?:[a-zA-Z_][a-zA-Z0-9_]*)?\s*\{([^}]+)\}'
for match in re.finditer(enum_member_pattern, no_comments, re.DOTALL):
members = match.group(1)
for member in re.finditer(r'\b([A-Z_][A-Z0-9_]*)\s*(?:=|,|(?=\}))', members):
member_name = member.group(1)
if member_name not in ['INT32_MIN', 'INT32_MAX', 'UINT32_MAX']:
enums[member_name] = filepath
return functions, macros, enums
def count_symbol_usage(files, symbol, is_macro=False):
"""Count how many times a symbol is referenced.
Note: This function uses simple pattern matching and may not detect all
forms of indirect usage, such as macro token concatenation (##NAME).
"""
count = 0
for filepath in files:
try:
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
except (IOError, OSError):
continue
# Remove comments
no_comments = re.sub(r'/\*.*?\*/', '', content, flags=re.DOTALL)
no_comments = re.sub(r'//.*?$', '', no_comments, flags=re.MULTILINE)
if is_macro:
# For macros, check various uses
patterns = [
r'#\s*if(?:n?def)?\s+' + re.escape(symbol) + r'\b',
r'#\s*if\s+.*\bdefined\s*\(\s*' + re.escape(symbol) + r'\s*\)',
r'\b' + re.escape(symbol) + r'\b',
]
for pattern in patterns:
count += len(re.findall(pattern, no_comments))
else:
# For functions/enums, count occurrences
pattern = r'\b' + re.escape(symbol) + r'\b'
count += len(re.findall(pattern, no_comments))
return count
def main():
# Determine base directory (script location or current directory)
script_dir = Path(__file__).parent.absolute()
if (script_dir / 'lib').exists():
base_dir = str(script_dir)
else:
base_dir = os.getcwd()
lib_dir = os.path.join(base_dir, 'lib')
public_header = os.path.join(lib_dir, 'includes', 'nghttp2', 'nghttp2.h')
if not os.path.exists(lib_dir):
print(f"Error: lib directory not found at {lib_dir}")
print("Please run this script from the nghttp2 repository root")
return 1
print("Analyzing nghttp2 for unused private symbols...")
print("=" * 70)
lib_files = get_lib_files(lib_dir)
all_files = get_all_project_files(base_dir)
print(f"Found {len(lib_files)} library source files (excluding public headers)")
print(f"Found {len(all_files)} total source files in project")
public_symbols = get_public_api_symbols(public_header)
print(f"Found {len(public_symbols)} public API symbols")
all_functions = {}
all_macros = {}
all_enums = {}
for filepath in lib_files:
functions, macros, enums = extract_definitions(filepath)
all_functions.update(functions)
all_macros.update(macros)
all_enums.update(enums)
private_functions = {k: v for k, v in all_functions.items() if k not in public_symbols}
private_macros = {k: v for k, v in all_macros.items() if k not in public_symbols}
private_enums = {k: v for k, v in all_enums.items() if k not in public_symbols}
print(f"\nFound {len(private_functions)} private function definitions")
print(f"Found {len(private_macros)} private macro definitions")
print(f"Found {len(private_enums)} private enum definitions/members")
unused_functions = []
unused_macros = []
unused_enums = []
print("\nChecking for unused private functions...")
for i, (func, filepath) in enumerate(sorted(private_functions.items())):
if (i + 1) % 50 == 0:
print(f" Checked {i + 1}/{len(private_functions)}...")
usage_count = count_symbol_usage(all_files, func, is_macro=False)
# If symbol appears only once (its definition), it's unused
if usage_count <= 1:
unused_functions.append((func, filepath, usage_count))
print("Checking for unused private macros...")
for i, (macro, filepath) in enumerate(sorted(private_macros.items())):
usage_count = count_symbol_usage(all_files, macro, is_macro=True)
# Macros often appear twice (definition + possible use in #ifdef)
if usage_count <= 1:
unused_macros.append((macro, filepath, usage_count))
print("Checking for unused private enums...")
for i, (enum, filepath) in enumerate(sorted(private_enums.items())):
if (i + 1) % 50 == 0:
print(f" Checked {i + 1}/{len(private_enums)}...")
usage_count = count_symbol_usage(all_files, enum, is_macro=False)
if usage_count <= 1:
unused_enums.append((enum, filepath, usage_count))
# Print results
print("\n" + "=" * 70)
print("RESULTS")
print("=" * 70)
if unused_functions:
print(f"\nUnused Private Functions ({len(unused_functions)}):")
for func, filepath, count in sorted(unused_functions):
rel_path = os.path.relpath(filepath, base_dir)
print(f" - {func:50s} in {rel_path} (refs: {count})")
if unused_macros:
print(f"\nUnused Private Macros ({len(unused_macros)}):")
for macro, filepath, count in sorted(unused_macros):
rel_path = os.path.relpath(filepath, base_dir)
print(f" - {macro:50s} in {rel_path} (refs: {count})")
if unused_enums:
print(f"\nUnused Private Enums ({len(unused_enums)}):")
for enum, filepath, count in sorted(unused_enums):
rel_path = os.path.relpath(filepath, base_dir)
print(f" - {enum:50s} in {rel_path} (refs: {count})")
if not unused_functions and not unused_macros and not unused_enums:
print("\nNo unused private symbols found!")
else:
print(f"\nTotal: {len(unused_functions)} functions, {len(unused_macros)} macros, {len(unused_enums)} enums")
print("\nNote: This analysis uses simple pattern matching and may not detect:")
print(" - Macro token concatenation (e.g., ##NAME in macro expansions)")
print(" - Function pointers passed through complex call chains")
print(" - Symbols used only in platform-specific conditional compilation")
print("\nManual verification is recommended before removing any symbols.")
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@@ -750,16 +750,6 @@ void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
uint8_t *p;
altsvc = frame->payload;
if (payloadlen == 0) {
altsvc->origin = NULL;
altsvc->origin_len = 0;
altsvc->field_value = NULL;
altsvc->field_value_len = 0;
return;
}
p = payload;
altsvc->origin = p;

View File

@@ -5466,10 +5466,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
busy = 1;
rv = session_on_data_received_fail_fast(session);
if (nghttp2_is_fatal(rv)) {
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (nghttp2_ssize)inlen;
}
@@ -5490,6 +5486,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
break;
}
if (nghttp2_is_fatal(rv)) {
return rv;
}
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
if (rv < 0) {
rv = nghttp2_session_terminate_session_with_reason(
@@ -5573,10 +5573,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (nghttp2_ssize)inlen;
}
on_begin_frame_called = 1;
rv = session_process_headers_frame(session);
@@ -6045,10 +6041,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
if (nghttp2_is_fatal(rv)) {
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (nghttp2_ssize)inlen;
}
}
}
@@ -6301,10 +6293,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (nghttp2_ssize)inlen;
}
session_inbound_frame_reset(session);
break;
@@ -6611,10 +6599,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
if (nghttp2_is_fatal(rv)) {
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (nghttp2_ssize)inlen;
}
} else {
iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
}
@@ -6787,17 +6771,13 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
rv = session->callbacks.on_data_chunk_recv_callback(
session, iframe->frame.hd.flags, iframe->frame.hd.stream_id,
in - readlen, (size_t)data_readlen, session->user_data);
if (nghttp2_is_fatal(rv)) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (nghttp2_ssize)inlen;
}
if (rv == NGHTTP2_ERR_PAUSE) {
return (nghttp2_ssize)(in - first);
}
if (nghttp2_is_fatal(rv)) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
}
}
}
@@ -6881,10 +6861,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (nghttp2_ssize)inlen;
}
if (rv != 0) {
busy = 1;
@@ -6903,10 +6879,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (nghttp2_ssize)inlen;
}
session_inbound_frame_reset(session);
break;
@@ -6935,10 +6907,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (nghttp2_ssize)inlen;
}
session_inbound_frame_reset(session);
break;

View File

@@ -375,18 +375,23 @@ constexpr size_t quote_stringlen(R &&r) {
return n;
}
inline constexpr auto hexdigits = []() {
constexpr char LOWER_XDIGITS[] = "0123456789abcdef";
inline constexpr char LOWER_XDIGITS[] = "0123456789abcdef";
std::array<char, 512> tbl;
template <std::weakly_incrementable O>
requires(std::indirectly_writable<O, char>)
constexpr O format_hex_uint8(uint8_t b, O result) {
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif // __GNUC__
*result++ = LOWER_XDIGITS[b >> 4];
*result++ = LOWER_XDIGITS[b & 0xf];
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif // __GNUC__
for (size_t i = 0; i < 256; ++i) {
tbl[i * 2] = LOWER_XDIGITS[static_cast<size_t>(i >> 4)];
tbl[i * 2 + 1] = LOWER_XDIGITS[static_cast<size_t>(i & 0xf)];
}
return tbl;
}();
return result;
}
// Converts a range [|first|, |last|) in hex format, and stores the
// result in another range, beginning at |result|. It returns an
@@ -396,9 +401,7 @@ requires(std::indirectly_writable<O, char> &&
sizeof(std::iter_value_t<I>) == sizeof(uint8_t))
constexpr O format_hex(I first, I last, O result) {
for (; first != last; ++first) {
result = std::ranges::copy_n(
hexdigits.data() + static_cast<uint8_t>(*first) * 2, 2, result)
.out;
result = format_hex_uint8(static_cast<uint8_t>(*first), result);
}
return result;
@@ -449,7 +452,7 @@ template <std::unsigned_integral T, std::weakly_incrementable O>
requires(std::indirectly_writable<O, char>)
constexpr O format_hex(T n, O result) {
if constexpr (sizeof(n) == 1) {
return std::ranges::copy_n(hexdigits.data() + n * 2, 2, result).out;
return format_hex_uint8(n, result);
}
if constexpr (std::endian::native == std::endian::little) {
@@ -457,38 +460,36 @@ constexpr O format_hex(T n, O result) {
auto p = end + sizeof(n);
for (; p != end; --p) {
result =
std::ranges::copy_n(hexdigits.data() + *(p - 1) * 2, 2, result).out;
result = format_hex_uint8(*(p - 1), result);
}
} else {
auto p = reinterpret_cast<uint8_t *>(&n);
auto end = p + sizeof(n);
for (; p != end; ++p) {
result = std::ranges::copy_n(hexdigits.data() + *p * 2, 2, result).out;
result = format_hex_uint8(*p, result);
}
}
return result;
}
inline constexpr auto upper_hexdigits = []() {
constexpr char UPPER_XDIGITS[] = "0123456789ABCDEF";
std::array<char, 512> tbl;
for (size_t i = 0; i < 256; ++i) {
tbl[i * 2] = UPPER_XDIGITS[static_cast<size_t>(i >> 4)];
tbl[i * 2 + 1] = UPPER_XDIGITS[static_cast<size_t>(i & 0xf)];
}
return tbl;
}();
inline constexpr char UPPER_XDIGITS[] = "0123456789ABCDEF";
template <std::weakly_incrementable O>
requires(std::indirectly_writable<O, char>)
constexpr O format_upper_hex(uint8_t c, O result) {
return std::ranges::copy_n(upper_hexdigits.data() + c * 2, 2, result).out;
constexpr O format_upper_hex_uint8(uint8_t b, O result) {
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif // __GNUC__
*result++ = UPPER_XDIGITS[b >> 4];
*result++ = UPPER_XDIGITS[b & 0xf];
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif // __GNUC__
return result;
}
// decode_hex decodes hex string in a range [|first|, |last|), and
@@ -558,7 +559,7 @@ constexpr O percent_encode_token(I first, I last, O result) noexcept {
}
*result++ = '%';
result = format_upper_hex(c, result);
result = format_upper_hex_uint8(c, result);
}
return result;
@@ -893,11 +894,11 @@ struct CompactHexFormatter {
assert(p != end);
if (*(p - 1) < 16) {
*result++ = static_cast<result_type>(upper_hexdigits[*--p * 2 + 1]);
*result++ = static_cast<result_type>(UPPER_XDIGITS[(*--p) & 0xf]);
}
for (; p != end; --p) {
result = format_upper_hex(*(p - 1), result);
result = format_upper_hex_uint8(*(p - 1), result);
}
} else {
auto p = reinterpret_cast<uint8_t *>(&n);
@@ -907,11 +908,11 @@ struct CompactHexFormatter {
;
if (*p < 16) {
*result++ = static_cast<result_type>(upper_hexdigits[*p++ * 2 + 1]);
*result++ = static_cast<result_type>(UPPER_XDIGITS[(*p++) & 0xf]);
}
for (; p != end; ++p) {
result = format_upper_hex(*p, result);
result = format_upper_hex_uint8(*p, result);
}
}

View File

@@ -82,7 +82,7 @@ const MunitTest tests[]{
munit_void_test(test_util_make_hostport),
munit_void_test(test_util_random_alpha_digit),
munit_void_test(test_util_format_hex),
munit_void_test(test_util_format_upper_hex),
munit_void_test(test_util_format_upper_hex_uint8),
munit_void_test(test_util_is_hex_string),
munit_void_test(test_util_decode_hex),
munit_void_test(test_util_extract_host),
@@ -890,31 +890,45 @@ void test_util_format_hex(void) {
(std::string_view{std::ranges::begin(buf),
util::format_hex(std::numeric_limits<uint64_t>::max(),
std::ranges::begin(buf))}));
std::vector<char> char_vec;
util::format_hex(0xdeadbeef, std::back_inserter(char_vec));
assert_stdsv_equal("deadbeef"sv,
(std::string_view{std::ranges::begin(char_vec),
std::ranges::end(char_vec)}));
std::vector<uint8_t> uint8_vec;
util::format_hex(0xdeadbeef, std::back_inserter(uint8_vec));
assert_stdsv_equal(
"deadbeef"sv,
(std::string_view{reinterpret_cast<const char *>(uint8_vec.data()),
uint8_vec.size()}));
}
void test_util_format_upper_hex(void) {
void test_util_format_upper_hex_uint8(void) {
std::array<char, 64> buf;
assert_stdsv_equal("00"sv, (std::string_view{std::ranges::begin(buf),
util::format_upper_hex_uint8(
0, std::ranges::begin(buf))}));
assert_stdsv_equal(
"00"sv,
(std::string_view{std::ranges::begin(buf),
util::format_upper_hex(0, std::ranges::begin(buf))}));
"0A"sv, (std::string_view{
std::ranges::begin(buf),
util::format_upper_hex_uint8(0xa, std::ranges::begin(buf))}));
assert_stdsv_equal(
"0A"sv,
(std::string_view{std::ranges::begin(buf),
util::format_upper_hex(0xa, std::ranges::begin(buf))}));
"7C"sv, (std::string_view{
std::ranges::begin(buf),
util::format_upper_hex_uint8(0x07c, std::ranges::begin(buf))}));
assert_stdsv_equal(
"7C"sv,
(std::string_view{std::ranges::begin(buf),
util::format_upper_hex(0x07c, std::ranges::begin(buf))}));
"EB"sv, (std::string_view{
std::ranges::begin(buf),
util::format_upper_hex_uint8(0xeb, std::ranges::begin(buf))}));
assert_stdsv_equal(
"EB"sv,
(std::string_view{std::ranges::begin(buf),
util::format_upper_hex(0xeb, std::ranges::begin(buf))}));
assert_stdsv_equal(
"FF"sv,
(std::string_view{std::ranges::begin(buf),
util::format_upper_hex(0xff, std::ranges::begin(buf))}));
"FF"sv, (std::string_view{
std::ranges::begin(buf),
util::format_upper_hex_uint8(0xff, std::ranges::begin(buf))}));
}
void test_util_is_hex_string(void) {

View File

@@ -69,7 +69,7 @@ munit_void_test_decl(test_util_make_http_hostport)
munit_void_test_decl(test_util_make_hostport)
munit_void_test_decl(test_util_random_alpha_digit)
munit_void_test_decl(test_util_format_hex)
munit_void_test_decl(test_util_format_upper_hex)
munit_void_test_decl(test_util_format_upper_hex_uint8)
munit_void_test_decl(test_util_is_hex_string)
munit_void_test_decl(test_util_decode_hex)
munit_void_test_decl(test_util_extract_host)

View File

@@ -515,24 +515,6 @@ void test_nghttp2_frame_pack_altsvc(void) {
nghttp2_frame_altsvc_free(&oframe, mem);
nghttp2_frame_altsvc_free(&frame, mem);
/* 0 length origin and field_value */
nghttp2_frame_altsvc_init(&frame, 0, NULL, 0, NULL, 0);
payloadlen = 2;
nghttp2_bufs_reset(&bufs);
nghttp2_frame_pack_altsvc(&bufs, &frame);
assert_size(NGHTTP2_FRAME_HDLEN + payloadlen, ==, nghttp2_bufs_len(&bufs));
nghttp2_frame_unpack_altsvc_payload(&oframe, 0, NULL, 0);
assert_size(0, ==, oaltsvc.origin_len);
assert_null(oaltsvc.origin);
assert_size(0, ==, oaltsvc.field_value_len);
assert_null(oaltsvc.field_value);
nghttp2_bufs_free(&bufs);
}

View File

@@ -157,7 +157,6 @@ static const MunitTest tests[] = {
munit_void_test(test_nghttp2_session_set_stream_user_data),
munit_void_test(test_nghttp2_session_no_rfc7540_priorities),
munit_void_test(test_nghttp2_session_stream_reset_ratelim),
munit_void_test(test_nghttp2_session_verify_iframe_state),
munit_void_test(test_nghttp2_http_mandatory_headers),
munit_void_test(test_nghttp2_http_content_length),
munit_void_test(test_nghttp2_http_content_length_mismatch),
@@ -10161,443 +10160,6 @@ void test_nghttp2_session_stream_reset_ratelim(void) {
nghttp2_option_del(option);
}
static int term_session_on_invalid_frame_recv_callback(
nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code,
void *user_data) {
int rv;
(void)frame;
(void)lib_error_code;
(void)user_data;
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
assert_int(0, ==, rv);
return 0;
}
static int term_session_on_begin_frame_callback(nghttp2_session *session,
const nghttp2_frame_hd *hd,
void *user_data) {
int rv;
(void)hd;
(void)user_data;
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
assert_int(0, ==, rv);
return 0;
}
static int term_session_on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data) {
int rv;
(void)frame;
(void)user_data;
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
assert_int(0, ==, rv);
return 0;
}
static int term_session_on_data_chunk_recv_callback(
nghttp2_session *session, uint8_t flags, int32_t stream_id,
const uint8_t *data, size_t len, void *user_data) {
int rv;
(void)flags;
(void)stream_id;
(void)data;
(void)len;
(void)user_data;
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
assert_int(0, ==, rv);
return 0;
}
static int term_session_unpack_extension_callback(nghttp2_session *session,
void **payload,
const nghttp2_frame_hd *hd,
void *user_data) {
int rv;
(void)payload;
(void)hd;
(void)user_data;
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
assert_int(0, ==, rv);
return 0;
}
static int term_session_on_extension_chunk_recv_callback(
nghttp2_session *session, const nghttp2_frame_hd *hd, const uint8_t *data,
size_t len, void *user_data) {
int rv;
(void)hd;
(void)data;
(void)len;
(void)user_data;
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
assert_int(0, ==, rv);
return NGHTTP2_ERR_CANCEL;
}
void test_nghttp2_session_verify_iframe_state(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_bufs bufs;
nghttp2_buf *buf;
nghttp2_frame frame;
nghttp2_extension extfr;
nghttp2_ext_priority_update priority_update;
nghttp2_ext_altsvc altsvc;
nghttp2_frame_hd hd;
uint8_t size_err_hd[NGHTTP2_FRAME_HDLEN];
nghttp2_ssize rv;
const char field_value[] = "i";
nghttp2_option *option;
nghttp2_hd_deflater deflater;
size_t nvlen;
nghttp2_nv *nva;
nghttp2_mem *mem = nghttp2_mem_default();
my_user_data ud;
nghttp2_buf udbuf;
const char uddata[] = "hello world";
nghttp2_frame_hd_init(&hd, 0, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE, 1);
nghttp2_frame_pack_frame_hd(size_err_hd, &hd);
nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
nghttp2_buf_init2(&udbuf, 4096, mem);
nghttp2_frame_hd_init(&hd, sizeof(uddata) - 1, 111, 0xab, 1000000007);
nghttp2_frame_pack_frame_hd(udbuf.last, &hd);
udbuf.last += NGHTTP2_FRAME_HDLEN;
udbuf.last = nghttp2_cpymem(udbuf.last, uddata, sizeof(uddata) - 1);
nghttp2_option_new(&option);
nghttp2_option_set_builtin_recv_extension_type(option,
NGHTTP2_PRIORITY_UPDATE);
nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
nghttp2_option_set_user_recv_extension_type(option, 111);
frame_pack_bufs_init(&bufs);
/* ALTSVC + on_invalid_frame_recv_callback + FRAME_SIZE_ERROR */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.on_invalid_frame_recv_callback =
term_session_on_invalid_frame_recv_callback;
nghttp2_session_client_new2(&session, &callbacks, NULL, option);
extfr.payload = &altsvc;
nghttp2_frame_altsvc_init(&extfr, 0, NULL, 0, NULL, 0);
nghttp2_bufs_reset(&bufs);
nghttp2_frame_pack_altsvc(&bufs, &extfr);
buf = &bufs.head->buf;
rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_session_del(session);
/* HEADERS + on_begin_frame_callback + FRAME_SIZE_ERROR */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.on_begin_frame_callback = term_session_on_begin_frame_callback;
nghttp2_session_server_new(&session, &callbacks, NULL);
nvlen = ARRLEN(reqnv);
nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
nghttp2_hd_deflate_init(&deflater, mem);
nghttp2_bufs_reset(&bufs);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
assert_ptrdiff(0, ==, rv);
nghttp2_frame_headers_free(&frame.headers, mem);
buf = &bufs.head->buf;
rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_hd_deflate_free(&deflater);
nghttp2_session_del(session);
/* Any frame (other than HEADERS) + on_begin_frame_callback +
FRAME_SIZE_ERROR */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.on_begin_frame_callback = term_session_on_begin_frame_callback;
nghttp2_session_server_new(&session, &callbacks, NULL);
nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_NO_ERROR);
nghttp2_bufs_reset(&bufs);
nghttp2_frame_pack_rst_stream(&bufs, &frame.rst_stream);
buf = &bufs.head->buf;
rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_session_del(session);
/* PRIORITY_UPDATE + on_frame_recv_callback + FRAME_SIZE_ERROR */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.on_frame_recv_callback = term_session_on_frame_recv_callback;
nghttp2_session_server_new2(&session, &callbacks, NULL, option);
extfr.payload = &priority_update;
nghttp2_frame_priority_update_init(&extfr, 1, (uint8_t *)field_value,
sizeof(field_value) - 1);
nghttp2_bufs_reset(&bufs);
nghttp2_frame_pack_priority_update(&bufs, &extfr);
buf = &bufs.head->buf;
rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_session_del(session);
/* ALTSVC + on_frame_recv_callback + FRAME_SIZE_ERROR */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.on_frame_recv_callback = term_session_on_frame_recv_callback;
nghttp2_session_client_new2(&session, &callbacks, NULL, option);
extfr.payload = &altsvc;
nghttp2_frame_altsvc_init(&extfr, 0, (uint8_t *)"nghttp2.org",
sizeof("nghttp2.org") - 1, (uint8_t *)"h2",
sizeof("h2") - 1);
nghttp2_bufs_reset(&bufs);
nghttp2_frame_pack_altsvc(&bufs, &extfr);
buf = &bufs.head->buf;
rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_session_del(session);
/* user-defined extension frame + on_frame_recv_callback +
FRAME_SIZE_ERROR */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.on_frame_recv_callback = term_session_on_frame_recv_callback;
callbacks.unpack_extension_callback = unpack_extension_callback;
nghttp2_session_server_new2(&session, &callbacks, &ud, option);
nghttp2_buf_reset(&ud.scratchbuf);
rv = nghttp2_session_mem_recv2(session, udbuf.pos, nghttp2_buf_len(&udbuf));
assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&udbuf), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_session_del(session);
/* DATA + on_data_chunk_recv_callback + FRAME_SIZE_ERROR*/
memset(&callbacks, 0, sizeof(callbacks));
callbacks.on_data_chunk_recv_callback =
term_session_on_data_chunk_recv_callback;
nghttp2_session_server_new(&session, &callbacks, NULL);
nvlen = ARRLEN(reqnv);
nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
nghttp2_hd_deflate_init(&deflater, mem);
nghttp2_bufs_reset(&bufs);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
assert_ptrdiff(0, ==, rv);
nghttp2_frame_headers_free(&frame.headers, mem);
buf = &bufs.head->buf;
rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_READ_HEAD, ==,
session->iframe.state);
nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
nghttp2_bufs_reset(&bufs);
nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
memset(bufs.head->buf.last, 0, 10);
bufs.head->buf.last += 10;
buf = &bufs.head->buf;
rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_hd_deflate_free(&deflater);
nghttp2_session_del(session);
/* user-defined extension frame + on_extension_chunk_recv_callback +
FRAME_SIZE_ERROR */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.on_extension_chunk_recv_callback =
term_session_on_extension_chunk_recv_callback;
callbacks.unpack_extension_callback = unpack_extension_callback;
nghttp2_session_server_new2(&session, &callbacks, &ud, option);
nghttp2_buf_reset(&ud.scratchbuf);
rv = nghttp2_session_mem_recv2(session, udbuf.pos, nghttp2_buf_len(&udbuf));
assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&udbuf), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_session_del(session);
/* user-defined extension frame + unpack_extension_callback +
FRAME_SIZE_ERROR */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.unpack_extension_callback = term_session_unpack_extension_callback;
nghttp2_session_server_new2(&session, &callbacks, &ud, option);
nghttp2_buf_reset(&ud.scratchbuf);
rv = nghttp2_session_mem_recv2(session, udbuf.pos, nghttp2_buf_len(&udbuf));
assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&udbuf), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_session_del(session);
/* PRIORITY_UPDATE on stream 1 + FRAME_SIZE_ERROR */
memset(&callbacks, 0, sizeof(callbacks));
nghttp2_session_server_new2(&session, &callbacks, NULL, option);
extfr.payload = &priority_update;
nghttp2_frame_priority_update_init(&extfr, 1, (uint8_t *)field_value,
sizeof(field_value) - 1);
nghttp2_bufs_reset(&bufs);
nghttp2_frame_pack_priority_update(&bufs, &extfr);
buf = &bufs.head->buf;
/* Set invalid stream ID 1 */
buf->pos[5 + sizeof(uint32_t) - 1] = 1;
rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd));
assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv);
assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
session->iframe.state);
nghttp2_session_del(session);
nghttp2_buf_free(&udbuf, mem);
nghttp2_buf_free(&ud.scratchbuf, mem);
nghttp2_bufs_free(&bufs);
nghttp2_option_del(option);
}
typedef struct check_http_opts {
int server;
int connect_protocol;

View File

@@ -153,7 +153,6 @@ munit_void_test_decl(test_nghttp2_session_no_closed_streams)
munit_void_test_decl(test_nghttp2_session_set_stream_user_data)
munit_void_test_decl(test_nghttp2_session_no_rfc7540_priorities)
munit_void_test_decl(test_nghttp2_session_stream_reset_ratelim)
munit_void_test_decl(test_nghttp2_session_verify_iframe_state)
munit_void_test_decl(test_nghttp2_http_mandatory_headers)
munit_void_test_decl(test_nghttp2_http_content_length)
munit_void_test_decl(test_nghttp2_http_content_length_mismatch)