Skip to content

Commit 8507abd

Browse files
committed
Merge FEATURE-v3-source-layout: separate library definitions from headers
2 parents eb1e56f + 2fee606 commit 8507abd

233 files changed

Lines changed: 12789 additions & 10331 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,6 @@ __pycache__/
166166
!scripts/run-v3-packaged-adapters.py
167167
!scripts/check-v3-public-http1.py
168168
!scripts/test-v3-packaged-adapters.py
169+
170+
# v3 source-layout compiled implementation contract checker.
171+
!scripts/check-v3-compiled-operations.py

‎CONTRIBUTING.md‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,18 @@ Please open an issue on `etr/libhttpserver` if you have suggestions for new labe
243243

244244
[beginner]:https://github.com/search?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+label%3Abeginner+label%3Ahelp-wanted+user%3Aetr+sort%3Acomments-desc
245245
[help-wanted]:https://github.com/search?q=is%3Aopen+is%3Aissue+label%3Ahelp-wanted+user%3Aetr+sort%3Acomments-desc+-label%3Abeginner
246+
247+
## v3 source ownership
248+
249+
On the `v3` branch, public compiled operations live in `src/<logical>.cpp`,
250+
owned by installed `src/httpserver/<logical>.hpp`. Private implementations and
251+
shared headers live in `src/detail/` and noninstalled `src/httpserver/detail/`.
252+
Cohesive split translation units share the actual owning header; do not create
253+
dummy headers or recombine engines just to match filenames.
254+
255+
Normal library linkage supplies non-template behavior. Keep templates and
256+
constexpr definitions visible to consumers, along with trivial accessors/value
257+
operations and justified small byte/arithmetic primitives. Preserve complete
258+
public representation and required template support in installed headers; an
259+
installed header must never include a noninstalled private/provider/platform
260+
header. Record ownership and inline exceptions in `docs/v3-source-layout.md`.

‎Makefile.am‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ check-hygiene:
278278
# still runs the full test suite plus the header / example / lint gates, but
279279
# skips the source-only doc gates whose inputs it cannot satisfy. Release runners
280280
# may provide a verified specs/ tooling bundle; it is not a source checkout.
281-
check-local: check-headers check-examples lint-warning-suppressions lint-littletest-skip-exit-code lint-fence-balance check-v3-native-linkage
281+
check-local: check-v3-compiled-operations check-headers check-examples lint-warning-suppressions lint-littletest-skip-exit-code lint-fence-balance check-v3-native-linkage
282282
@if test -d "$(top_srcdir)/specs" && test -e "$(top_srcdir)/.git"; then \
283283
$(MAKE) $(AM_MAKEFLAGS) check-readme check-release-notes check-doxygen ; \
284284
else \
@@ -611,3 +611,10 @@ EXTRA_DIST += test/installed/task199-capabilities.md \
611611

612612
EXTRA_DIST += scripts/lib/v3_examples.py scripts/lib/v3_example_consumers.py \
613613
specs/architecture/v3/v2-parity-inventory.md
614+
615+
EXTRA_DIST += docs/v3-source-layout.md scripts/check-v3-compiled-operations.py
616+
617+
check-v3-compiled-operations: $(top_builddir)/src/libhttpserver.la
618+
python3 $(top_srcdir)/scripts/check-v3-compiled-operations.py $(top_builddir)/src/.libs/libhttpserver.a
619+
620+
.PHONY: check-v3-compiled-operations

‎docs/v3-source-layout.md‎

Lines changed: 1035 additions & 0 deletions
Large diffs are not rendered by default.

‎scripts/audit-v3-native-linkage.sh‎

Lines changed: 152 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,10 @@ src/httpserver/websocket/session.hpp
8181
"
8282

8383
V3CORE_SOURCES="
84-
src/detail/features.cpp
85-
src/detail/server_tls_credentials.cpp
84+
src/detail/tls_psk.cpp
85+
src/server/tls_psk.cpp
86+
src/server/tls_credentials.cpp
87+
src/features.cpp
8688
src/detail/io_operation.cpp
8789
src/detail/io_udp_backend.cpp
8890
src/detail/quic_invariant_header.cpp
@@ -95,26 +97,162 @@ src/detail/io_kqueue_backend.cpp
9597
src/detail/io_iocp_backend.cpp
9698
src/detail/io_managed_backend.cpp
9799
src/detail/io_managed_socket_backend.cpp
100+
src/detail/io_external_adapter.cpp
101+
src/detail/io_wake_source.cpp
98102
src/detail/worker_pool.cpp
99103
src/detail/connection_engine.cpp
100104
src/detail/connection_engine_request.cpp
101105
src/detail/listener_engine.cpp
102-
src/detail/server.cpp
103-
src/detail/auth_basic.cpp
104-
src/detail/auth_digest.cpp
105-
src/detail/forms_urlencoded.cpp
106-
src/detail/forms_multipart.cpp
107-
src/detail/forms_multipart_files.cpp
108-
src/detail/server_hooks.cpp
106+
src/detail/drain_scope.cpp
107+
src/server/server.cpp
108+
src/auth/basic_auth.cpp
109+
src/auth/digest_auth.cpp
110+
src/forms/urlencoded.cpp
111+
src/forms/multipart.cpp
112+
src/forms/multipart_files.cpp
113+
src/server/hooks.cpp
109114
src/detail/request_lifecycle.cpp
110-
src/detail/net_address.cpp
115+
src/net/address.cpp
111116
src/detail/peer_policy.cpp
112-
src/detail/http1_websocket_handshake.cpp
113-
src/detail/connection_engine_websocket.cpp
114-
src/detail/websocket_driver.cpp
115117
src/detail/websocket_codec.cpp
118+
src/detail/websocket_driver.cpp
116119
src/detail/websocket_session_state.cpp
117-
src/detail/websocket_session.cpp
120+
src/websocket/session.cpp
121+
src/detail/http1_websocket_handshake.cpp
122+
src/detail/connection_engine_websocket.cpp
123+
src/detail/http2_frame.cpp
124+
src/detail/http2_connection.cpp
125+
src/detail/http2_request_engine.cpp
126+
src/detail/http2_native_stream.cpp
127+
src/detail/http2_native_timers.cpp
128+
src/detail/http2_tcp_owner.cpp
129+
src/detail/http2_request_head.cpp
130+
src/detail/http2_body_stream.cpp
131+
src/detail/http2_response_stream.cpp
132+
src/detail/http2_stream_flow.cpp
133+
src/detail/websocket_handshake.cpp
134+
src/detail/http2_websocket_handshake.cpp
135+
src/detail/http2_websocket_stream.cpp
136+
src/detail/quic_varint.cpp
137+
src/detail/quic_packet.cpp
138+
src/detail/quic_frame.cpp
139+
src/detail/quic_frame_write.cpp
140+
src/detail/quic_transport_parameters.cpp
141+
src/detail/quic_amplification.cpp
142+
src/detail/quic_stream_state.cpp
143+
src/detail/quic_reassembly.cpp
144+
src/detail/quic_ack_state.cpp
145+
src/detail/quic_recovery.cpp
146+
src/detail/quic_recovery_timer.cpp
147+
src/detail/quic_repacketize.cpp
148+
src/detail/quic_flow_control.cpp
149+
src/detail/quic_flow_receive.cpp
150+
src/detail/quic_flow_send.cpp
151+
src/detail/quic_storage.cpp
152+
src/detail/quic_recovery_flow.cpp
153+
src/detail/quic_congestion.cpp
154+
src/detail/quic_pacing.cpp
155+
src/detail/quic_send_schedule.cpp
156+
src/detail/quic_persistent_congestion.cpp
157+
src/detail/quic_recovery_emission.cpp
158+
src/detail/http3_frame.cpp
159+
src/detail/http3_connection.cpp
160+
src/detail/http3_settings.cpp
161+
src/detail/http3_request_head.cpp
162+
src/detail/http3_request_engine.cpp
163+
src/detail/http3_body_stream.cpp
164+
src/detail/http3_response_stream.cpp
165+
src/detail/quic_connection_identity.cpp
166+
src/detail/quic_path_mtu.cpp
167+
src/detail/quic_recovery_mtu.cpp
168+
src/detail/quic_datagram_sizing.cpp
169+
src/detail/quic_recovery_datagram.cpp
170+
src/detail/quic_connection_lifecycle.cpp
171+
src/detail/http3_qpack.cpp
172+
src/detail/http3_control_drain.cpp
173+
src/detail/http3_drain.cpp
174+
src/detail/http3_websocket_handshake.cpp
175+
src/detail/http3_websocket_handshake_stream.cpp
176+
src/detail/http3_websocket_stream.cpp
177+
src/server/diagnostics.cpp
178+
src/http/cookie.cpp
179+
src/detail/http3_native_stream.cpp
180+
src/detail/http3_semantic_stream.cpp
181+
src/http/method.cpp
182+
src/http/fields.cpp
183+
src/server/budgets.cpp
184+
src/server/route_sync.cpp
185+
src/server/routes.cpp
186+
src/server/options.cpp
187+
src/detail/net_address.cpp
188+
src/detail/diagnostics_access.cpp
189+
src/detail/tls_credentials_access.cpp
190+
src/detail/tls_psk_access.cpp
191+
src/detail/hook_bus.cpp
192+
src/response_definition.cpp
193+
src/body_reader.cpp
194+
src/exchange.cpp
195+
src/response_sources.cpp
196+
src/response_writer.cpp
197+
src/server/peer_policy.cpp
198+
src/detail/io_poll_sys.cpp
199+
src/detail/hpack_primitives.cpp
200+
src/detail/qpack_encoder.cpp
201+
src/detail/lifecycle_sink.cpp
202+
src/detail/hpack_decoder.cpp
203+
src/detail/qpack_decoder.cpp
204+
src/detail/qpack_instructions.cpp
205+
src/detail/sha1.cpp
206+
src/detail/secure_compare.cpp
207+
src/detail/http1_response_mode.cpp
208+
src/detail/digest_response.cpp
209+
src/detail/forms_verdict.cpp
210+
src/detail/resource_charge.cpp
211+
src/detail/hpack_encoder.cpp
212+
src/detail/websocket_utf8.cpp
213+
src/detail/quic_recovery_internal.cpp
214+
src/detail/request_handler_frames.cpp
215+
src/detail/http1_error_synth.cpp
216+
src/detail/md5.cpp
217+
src/detail/base64.cpp
218+
src/detail/sha256.cpp
219+
src/detail/http1_body_decoder.cpp
220+
src/detail/http1_body_mode.cpp
221+
src/detail/http1_response_outbox.cpp
222+
src/detail/exchange_runner.cpp
223+
src/detail/http1_response_framer.cpp
224+
src/detail/qpack_field_section.cpp
225+
src/detail/digest_ledger.cpp
226+
src/detail/entropy_sys.cpp
227+
src/detail/digest_nonce.cpp
228+
src/detail/http1_head_parser.cpp
229+
src/detail/http1_body_source.cpp
230+
src/detail/qpack_primitives.cpp
231+
src/detail/qpack_dynamic_table.cpp
232+
src/detail/forms_multipart.cpp
233+
src/detail/digest_hex.cpp
234+
src/detail/http2_request_state.cpp
235+
src/detail/io_timer_sweep.cpp
236+
src/detail/hpack_field_section.cpp
237+
src/detail/forms_urlencoded.cpp
238+
src/detail/auth_text.cpp
239+
src/detail/http1_target.cpp
240+
src/detail/hpack_dynamic_table.cpp
241+
src/detail/digest_params.cpp
242+
src/detail/http3_request_state.cpp
243+
src/detail/quic_flow_internal.cpp
244+
src/detail/multiplexed_request_head.cpp
245+
src/concurrency/cancellation.cpp
246+
src/concurrency/executor.cpp
247+
src/concurrency/task.cpp
248+
src/concurrency/resume_signal.cpp
249+
src/websocket/options.cpp
250+
src/detail/unescape_helpers.cpp
251+
src/detail/http1_host.cpp
252+
src/detail/io_poll_backend_timers.cpp
253+
src/detail/http2_dispatch.cpp
254+
src/detail/connection_engine_config.cpp
255+
src/detail/io_completion_storage.cpp
118256
"
119257

120258
# TASK-114: the in-tree codec/hash/entropy primitives the auth TU and
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env python3
2+
"""Check the installed-library implementation contract for representative operations."""
3+
import argparse
4+
import subprocess
5+
6+
# These operations must have a library-owned definition even when no consumer
7+
# instantiates them. Behavioral suites cover their semantics independently.
8+
OPERATIONS = (
9+
'httpserver::http::fields::append(',
10+
'httpserver::server::server_options::validate(',
11+
'httpserver::server::resource_budget::reserve(',
12+
'httpserver::server::route_pattern::parse(',
13+
'httpserver::server::make_sync_route(',
14+
'httpserver::manual_executor::run_one(',
15+
'httpserver::detail::current_executor_slot(',
16+
'httpserver::detail::task_frame_base::finish(',
17+
'httpserver::stop_token::cancellation_awaiter::await_suspend(',
18+
'httpserver::detail::fire_trigger(',
19+
'httpserver::exchange::admit_body(',
20+
'httpserver::body_reader::collect(',
21+
'httpserver::response_writer::finish(',
22+
'httpserver::response_definition::owned_bytes(',
23+
'httpserver::send_definition(',
24+
'httpserver::detail::send_cursor::pull(',
25+
'httpserver::detail::http1_head_parser::',
26+
'httpserver::detail::hpack_decoder::',
27+
'httpserver::detail::qpack_decoder::',
28+
'httpserver::websocket::options::validate(',
29+
'httpserver::detail::http2_dispatch::post(',
30+
'httpserver::detail::valid_http1_host(',
31+
'httpserver::detail::unescape_buf_raw(',
32+
'httpserver::detail::owned_completion_storage::claim_read(',
33+
)
34+
35+
36+
def main():
37+
parser = argparse.ArgumentParser(description=__doc__)
38+
parser.add_argument('library')
39+
args = parser.parse_args()
40+
result = subprocess.run(['nm', '-C', args.library],
41+
check=True, text=True, capture_output=True)
42+
definitions = [line for line in result.stdout.splitlines()
43+
if ' T ' in line]
44+
missing = [name for name in OPERATIONS if not any(name in line for line in definitions)]
45+
if missing:
46+
raise SystemExit('Missing compiled library operations:\n' + '\n'.join(missing))
47+
print('PASS representative operations have compiled library definitions')
48+
49+
50+
if __name__ == '__main__':
51+
main()

‎scripts/check-v3-installed-consumer.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,21 @@ def package_lane(args, source, output, mode, inventory):
9595
if cell['tls'] == mode and cell['linkage'] == linkage:
9696
public[linkage]['cells'].append(traffic(executable, cell, consumer_dir, runtime_env, inventory))
9797
(lane / 'public.json').write_text(json.dumps(public, indent=2))
98+
compiled_sources = []
99+
for name in ('v3_compiled_operations.cpp', 'v3_compiled_operations_worker.cpp'):
100+
copied = consumer_dir / name
101+
if not copied.exists():
102+
shutil.copyfile(source / 'test/installed' / name, copied)
103+
compiled_sources.append(copied)
104+
compiled_executable = consumer_dir / ('compiled_operations_' + linkage + suffix)
105+
compiled_provenance = compile_probe(args.compiler, compiled_sources, cflags, libraries,
106+
compiled_executable, command, runtime_env, source, build, prefix, False)
107+
compiled_graph = audit.dependency_graph([str(compiled_executable)])
108+
matrix.check_linkage(compiled_graph, linkage, prefix)
109+
command([str(compiled_executable)], consumer_dir, runtime_env)
110+
public[linkage]['compiled_operations'] = dict(compile=compiled_provenance, dependencies=compiled_graph)
111+
command([sys.executable, str(source / 'scripts/check-v3-compiled-operations.py'),
112+
str(prefix / 'lib/libhttpserver.a')], consumer_dir, runtime_env)
98113
private_dir = lane / ('integration-' + linkage)
99114
private_dir.mkdir()
100115
private_libraries = libraries + (shlex.split(env['V3_TLS_LIBS']) if mode == 'yes' else [])

‎scripts/run-v3-protocol-fuzz.sh‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,24 @@ PY
9393
esac
9494
[ -n "$(find "$build/$target/seeds" -type f -print -quit)" ] || { echo "empty corpus: $target" >&2; exit 1; }
9595
sources=("$root/test/fuzz/${target}_fuzz.cpp")
96-
if [ "$target" = http1_head ]; then sources+=("$root/src/detail/net_address.cpp"); fi
97-
if [ "$target" = websocket_codec ]; then sources+=("$root/src/detail/websocket_codec.cpp"); fi
96+
if [ "$target" = http1_head ] || [ "$target" = http1_body ] || [ "$target" = hpack ]; then
97+
sources+=("$root/src/http/fields.cpp" "$root/src/http/method.cpp"
98+
"$root/src/server/budgets.cpp" "$root/src/detail/resource_charge.cpp")
99+
fi
100+
if [ "$target" = http1_head ] || [ "$target" = http1_body ]; then
101+
sources+=("$root/src/net/address.cpp" "$root/src/detail/net_address.cpp"
102+
"$root/src/detail/http1_head_parser.cpp" "$root/src/detail/http1_body_mode.cpp" "$root/src/detail/http1_target.cpp"
103+
"$root/src/detail/http1_host.cpp" "$root/src/detail/unescape_helpers.cpp")
104+
fi
105+
if [ "$target" = http1_body ]; then
106+
sources+=("$root/src/detail/http1_body_decoder.cpp")
107+
fi
108+
if [ "$target" = hpack ]; then
109+
sources+=("$root/src/detail/hpack_primitives.cpp" "$root/src/detail/hpack_dynamic_table.cpp"
110+
"$root/src/detail/hpack_field_section.cpp" "$root/src/detail/hpack_decoder.cpp"
111+
"$root/src/detail/hpack_encoder.cpp")
112+
fi
113+
if [ "$target" = websocket_codec ]; then sources+=("$root/src/detail/websocket_codec.cpp" "$root/src/detail/websocket_utf8.cpp"); fi
98114
if [ "$target" = quic_parser ]; then
99115
sources+=("$root/src/detail/quic_invariant_header.cpp" "$root/src/detail/quic_varint.cpp"
100116
"$root/src/detail/quic_packet.cpp" "$root/src/detail/quic_frame.cpp"

‎specs/architecture/v3/architecture.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,23 @@ child receipts, commands, processes, depfiles, link maps, executables, fixtures
418418
and selected client/tool inputs. Both adapters use exclusive outputs and
419419
caller-bound run IDs, preserving failed attempts. No general stage registry or
420420
TASK-185 runner import is introduced. Its exact integration remains TASK-185 owned.
421+
422+
### Source ownership and compiled operations
423+
424+
Public non-template implementation is compiled in `src/<logical>.cpp`, paired
425+
with installed `src/httpserver/<logical>.hpp`. Private implementation is compiled
426+
in `src/detail/<logical>.cpp`, paired with noninstalled
427+
`src/httpserver/detail/<logical>.hpp`. Cohesive engine splits explicitly share
428+
their actual owning header; matching basenames do not require dummy headers or
429+
recombined protocol engines. Provider-conditioned implementation stays within
430+
the private provider target.
431+
432+
Templates and constexpr operations remain visible for instantiation and constant
433+
evaluation. Trivial accessors, value operations and small byte/arithmetic
434+
primitives may remain inline with the recorded reason in
435+
[the complete ownership inventory](../../../docs/v3-source-layout.md). Complete
436+
public representation and template support remain in installed headers, including
437+
necessary detail declarations. An installed header never includes a noninstalled
438+
private header. Normal library linkage supplies compiled operations; standalone
439+
header compilation does not imply link-free runtime behavior. Extraction preserves
440+
API, representation, suspension points, resource accounting and protocol behavior.

0 commit comments

Comments
 (0)