@@ -67,6 +67,154 @@ QUICPlugin::QUICPlugin([[maybe_unused]]const std::string& params, FieldManager&
6767 }
6868}
6969
70+ constexpr
71+ void QUICPlugin::tryToSetOCCIDandSCID (
72+ const QUICDirection quicDirection,
73+ std::span<const uint8_t > sourceConnectionId,
74+ std::span<const uint8_t > destinationConnectionId
75+ ) noexcept
76+ {
77+ const DirectionalField<std::span<const uint8_t >> currentIds;
78+ currentIds[QUICDirection::CLIENT_TO_SERVER] = destinationConnectionId;
79+ currentIds[QUICDirection::SERVER_TO_CLIENT] = sourceConnectionId;
80+
81+ ConnectionId serverId = m_temporalCIDStorage.getServerCID (quicDirection);
82+ if (!serverId.empty () && m_exportData.serverConnectionId .empty ()) {
83+ m_exportData.serverConnectionId = serverId;
84+ }
85+ if (!currentIds[quicDirection].empty () &&
86+ m_exportData.serverConnectionId .empty ()) {
87+ m_exportData.serverConnectionId = currentIds[quicDirection];
88+ }
89+
90+ ConnectionId originalClientId = m_temporalCIDStorage.getClientCID (quicDirection);
91+ if (!originalClientId.empty () && m_exportData.clientConnectionId .empty ()) {
92+ m_exportData.clientConnectionId = originalClientId;
93+ }
94+ if (!currentIds[!quicDirection].empty () &&
95+ m_exportData.clientConnectionId .empty ()) {
96+ m_exportData.clientConnectionId = currentIds[!quicDirection];
97+ }
98+ }
99+
100+ constexpr
101+ void QUICPlugin::saveConnectionIdsToTemporalBuffer (
102+ const Direction direction,
103+ std::span<const uint8_t > sourceConnectionId,
104+ std::span<const uint8_t > destinationConnectionId
105+ ) noexcept
106+ {
107+
108+ }
109+
110+
111+ constexpr
112+ void QUICPlugin::processInitial (
113+ const Direction flowDirection,
114+ const HeaderView& headerView,
115+ const InitialHeaderView& initialHeaderView,
116+ std::optional<QUICDirection> quicDirection) noexcept
117+ {
118+ m_initialConnectionId = initialHeaderView.destinationConnectionId ;
119+ if (!quicDirection.has_value ()) {
120+ // Server is still not revealed, so we store those values to emplace them
121+ // when directions are known
122+ m_temporalCIDStorage.storeConnectionIds (
123+ flowDirection,
124+ headerView.sourceConnectionId ,
125+ headerView.destinationConnectionId );
126+ return ;
127+ }
128+
129+ tryToSetOCCIDandSCID (...);
130+
131+ if (initialHeaderView.tlsHandshake .type != TLSHeader::Type::CLIENT_HELLO) {
132+ return ;
133+ }
134+
135+ if (initialHeaderView.tokenLength .has_value ()) {
136+ m_exportData.tokenLength = *initialHeaderView.tokenLength ;
137+ }
138+
139+ if (initialHeaderView.tokenLength .has_value () &&
140+ *initialHeaderView.tokenLength > 0 &&
141+ std::ranges::equal (
142+ m_exportData.retrySCID , m_exportData.destinationConnectionId )) {
143+ return ;
144+ }
145+
146+ // process multiplexing
147+ const bool hasMultiplexing =
148+ (std::ranges::equal (m_exportData.serverCID , destinationConnectionId) ||
149+ std::ranges::equal (m_exportData.sourceCID , destinationConnectionId)) &&
150+ std::ranges::equal (m_exportData.sni , initialHeaderView.sni );
151+ if (hasMultiplexing) {
152+ multiplexedCount = std::min<uint16_t >(
153+ multiplexedCount + 1 , std::numeric_limits<uint8_t >::max ());
154+ return ;
155+ }
156+
157+ m_exportData.userAgent = initialHeaderView.userAgent ;
158+ if (m_exportData.serverCID .empty ()) {
159+ m_exportData.serverCID = destinationConnectionId;
160+ }
161+ if (m_exportData.clientCID .empty ()) {
162+ m_exportData.clientCID = sourceConnectionId;
163+ }
164+ if (m_exportData.quicVersion == 0 ) {
165+ m_exportData.quicVersion = headerView.version ;
166+ }
167+
168+ if (m_exportData.tlsExtensionTypes .empty ()) {
169+ std::ranges::copy (initialHeaderView |
170+ std::views::transform ([](const TLSExtension& extension) {
171+ return extension.type ;
172+ }) |
173+ std::views::take (m_exportData.tlsExtensionTypes .capacity ()),
174+ std::back_inserter (m_exportData.tlsExtensionTypes ));
175+ }
176+
177+ if (m_exportData.tlsExtensionLengths .empty ()) {
178+ std::ranges::copy (initialHeaderView |
179+ std::views::transform ([](const TLSExtension& extension) {
180+ return extension.length ;
181+ }) |
182+ std::views::take (m_exportData.tlsExtensionLengths .capacity ()),
183+ std::back_inserter (m_exportData.tlsExtensionLengths ));
184+ }
185+
186+ if (m_exportData.extensionsPayload .empty ()) {
187+ std::ranges::copy (initialHeaderView.extensionsPayload |
188+ std::views::take (QUICExport::MAX_BUFFER_SIZE),
189+ std::back_inserter (m_exportData.extensionsPayload ));
190+ }
191+
192+
193+
194+ }
195+
196+ constexpr
197+ void QUICPlugin::parseRetry () noexcept
198+ {
199+ m_retryPacketCount++;
200+ /*
201+ * A client MUST accept and process at most one Retry packet for each connection
202+ * attempt. After the client has received and processed an Initial or Retry packet from
203+ * the server, it MUST discard any subsequent Retry packets that it receives.
204+ */
205+ if (m_retryPacketCount == 1 ) {
206+ // Additionally set token len
207+ m_exportData.retryCID = sourceConnectionId;
208+ m_initialCID = destinationConnectionId;
209+ m_exportData.tokenLength = 16 ; // ?????????
210+ }
211+
212+ if (m_exportData.clientCID .empty ()) {
213+ m_exportData.clientCID = destinationConnectionId;
214+ }
215+ }
216+
217+
70218int QUICPlugin::process_quic (
71219 RecordExtQUIC* quic_data,
72220 Flow& rec,
@@ -75,7 +223,11 @@ int QUICPlugin::process_quic(
75223{
76224 QUICParser quicParser;
77225
78- quicParser.parse (payload, initialDestConnectionId);
226+ if (!quicParser.parse (payload, initialDestConnectionId)) {
227+ // / ??????????????????????
228+ m_exportData.packets .push_back (packetTypeCumulativeWithQUICBitSet);
229+ return QUIC_NOT_DETECTED;
230+ }
79231
80232 if (quicParser.headerView .has_value () &&
81233 quicParser.packetTypesCumulative .bits .zeroRTT ) {
@@ -89,114 +241,56 @@ int QUICPlugin::process_quic(
89241
90242 // TODO get direction ?
91243
92- m_exportData.zeroRTTPacket = std::min<uint16_t >(
93- m_exportData.zeroRTTPacket + quicParser.zeroRTTPackets ,
94- std::numeric_limits<uint8_t >::max ()
95- );
244+ if (version == QUICVersionId::version_negotiation) {
245+ set_cid_fields (quic_data, rec, &process_quic, toServer, new_quic_flow, pkt);
246+ return FlowAction::Flush;
247+ }
248+
249+ if (quicParser.packetTypesCumulative .bits .zeroRTT ) {
250+ m_exportData.zeroRTTPacket = std::min<uint16_t >(
251+ m_exportData.zeroRTTPacket + quicParser.zeroRTTPackets ,
252+ std::numeric_limits<uint8_t >::max ()
253+ );
254+ }
255+
256+
96257
97258 if (quicParser.initialHeaderView .has_value ()) {
98259 m_exportData.clientHelloParsed
99260 = quicParser.initialHeaderView ->clientHelloParsed ;
100261 }
101262
102- switch (quicParser.packetType ) {
103- case QUICParser::PACKET_TYPE::INITIAL:
104- if (!quicParser.initialHeaderView .has_value ()) {
105- break ; // ??
106- }
107- process_quic.quic_get_parsed_initial (parsed_initial);
108- m_initialDestinationConnectionId.clear ();
109- std::ranges::copy (quicParser.initialHeaderView ->destinationConnectionId |
110- std::views::take (m_initialDestinationConnectionId.capacity ()),
111- std::back_inserter (m_initialDestinationConnectionId));
112- // Store DCID from first observed Initial packet. This is used in the crypto operations.
113- // Check length works because the first Initial must have a non-zero DCID.
114- if (quic_data->initial_dcid_length == 0 ) {
115- process_quic.quic_get_dcid_len (quic_data->initial_dcid_length );
116- process_quic.quic_get_dcid (quic_data->initial_dcid );
117- // Once established it can only be changed by a retry packet.
118- }
119- if (quicParser.initialHeaderView .has_value () &&
120- quicParser.initialHeaderView ->clientHelloParsed ) {
121-
122- if (m_exportData.sourceConnectionId .empty () &&
123- quicParser.packetDirection .has_value () &&
124- m_tempConnectionIdBuffer[*quicParser.packetDirection ].has_value ()) {
125- std::ranges::copy (
126- m_tempConnectionIdBuffer[*quicParser.packetDirection ].destinationConnectionId |
127- std::views::take (m_exportData.sourceConnectionId .capacity ()),
128- std::back_inserter (m_exportData.sourceConnectionId )
129- );
130- }
131- set_stored_cid_fields (quic_data, new_quic_flow);
132- set_client_hello_fields (&process_quic, rec, quic_data, pkt, new_quic_flow);
133- quic_data->client_hello_seen = true ;
134-
135- if (!quic_data->tls_ext_type_set ) {
136- process_quic.quic_get_tls_ext_type (quic_data->tls_ext_type );
137- process_quic.quic_get_tls_ext_type_len (quic_data->tls_ext_type_len );
138- quic_data->tls_ext_type_set = true ;
139- }
140-
141- if (!quic_data->tls_ext_len_set ) {
142- process_quic.quic_get_tls_extension_lengths (quic_data->tls_ext_len );
143- process_quic.quic_get_tls_extension_lengths_len (quic_data->tls_ext_len_len );
144- quic_data->tls_ext_len_set = true ;
145- }
263+ if (!m_temporalCIDStorage.directionIsRevealed () &&
264+ quicParser.quicDirection .has_value ()) {
265+ m_temporalCIDStorage.pairDirections (
266+ *quicParser.quicDirection , packet.direction );
267+ }
146268
147- if (!quic_data->tls_ext_set ) {
148- process_quic.quic_get_tls_ext (quic_data->tls_ext );
149- process_quic.quic_get_tls_ext_len (quic_data->tls_ext_length );
150- quic_data->tls_ext_set = true ;
151- }
269+ switch (quicParser.packetType ) {
270+ case QUICParser::PACKET_TYPE::INITIAL: {
271+ processInitial (...);
272+ break ;
273+ }
274+ case QUICParser::PACKET_TYPE::HANDSHAKE:{
275+ if (!quicDirection.has_value ()) {
276+ m_temporalCIDStorage.storeConnectionIds (
277+ flowDirection,
278+ headerView.sourceConnectionId ,
279+ headerView.destinationConnectionId );
152280 break ;
153281 }
154-
155- // Update accounting for information from CH, SH.
156- toServer = get_direction_to_server_and_set_port (
157- &process_quic,
158- quic_data,
159- process_quic.quic_get_server_port (),
160- pkt,
161- new_quic_flow);
162- // fallthrough to set cids
163- [[fallthrough]];
164- case QUICParser::PACKET_TYPE::HANDSHAKE:
165- // -1 sets stores intermediately.
166- set_cid_fields (quic_data, rec, &process_quic, toServer, new_quic_flow, pkt);
282+ tryToSetOCCIDandSCID (...);
167283 break ;
168- case QUICParser::PACKET_TYPE::RETRY:
169- quic_data->cnt_retry_packets += 1 ;
170- /*
171- * A client MUST accept and process at most one Retry packet for each connection
172- * attempt. After the client has received and processed an Initial or Retry packet from
173- * the server, it MUST discard any subsequent Retry packets that it receives.
174- */
175- if (quic_data->cnt_retry_packets == 1 ) {
176- // Additionally set token len
177- process_quic.quic_get_scid (quic_data->retry_scid );
178- process_quic.quic_get_scid_len (quic_data->retry_scid_length );
179- // Update DCID for decryption
180- process_quic.quic_get_dcid_len (quic_data->initial_dcid_length );
181- process_quic.quic_get_scid (quic_data->initial_dcid );
182-
183- process_quic.quic_get_token_length (quic_data->quic_token_length );
184- }
185-
186- if (!quic_data->occid_set ) {
187- process_quic.quic_get_dcid (quic_data->occid );
188- process_quic.quic_get_dcid_len (quic_data->occid_length );
189- quic_data->occid_set = true ;
190- }
191-
284+ }
285+ case QUICParser::PACKET_TYPE::RETRY: {
286+ parseRetry (...);
192287 break ;
288+ }
193289 case QUICParser::PACKET_TYPE::ZERO_RTT:
194290 // Connection IDs are identical to Client Initial CH. The DCID might be OSCID at first
195291 // and change to SCID later. We ignore the DCID.
196- if (!quic_data->occid_set ) {
197- process_quic.quic_get_scid (quic_data->occid );
198- process_quic.quic_get_scid_len (quic_data->occid_length );
199- quic_data->occid_set = true ;
292+ if (m_exportData.clientCID .empty ()) {
293+ m_exportData.clientCID = sourceConnectionId;
200294 }
201295 break ;
202296 }
0 commit comments