@@ -239,39 +239,83 @@ func (l *Listener) listen() {
239239func  (l  * Listener ) handleDatagram (m  * datagram , conns  map [string ]* Conn ) {
240240	dstConnID , ok  :=  dstConnIDForDatagram (m .b )
241241	if  ! ok  {
242+ 		m .recycle ()
242243		return 
243244	}
244245	c  :=  conns [string (dstConnID )]
245246	if  c  ==  nil  {
246- 		if  getPacketType (m .b ) !=  packetTypeInitial  {
247- 			// This packet isn't trying to create a new connection. 
248- 			// It might be associated with some connection we've lost state for. 
249- 			// TODO: Send a stateless reset when appropriate. 
250- 			// https://www.rfc-editor.org/rfc/rfc9000.html#section-10.3 
251- 			return 
252- 		}
253- 		var  now  time.Time 
254- 		if  l .testHooks  !=  nil  {
255- 			now  =  l .testHooks .timeNow ()
256- 		} else  {
257- 			now  =  time .Now ()
258- 		}
259- 		var  err  error 
260- 		c , err  =  l .newConn (now , serverSide , dstConnID , m .addr )
261- 		if  err  !=  nil  {
262- 			// The accept queue is probably full. 
263- 			// We could send a CONNECTION_CLOSE to the peer to reject the connection. 
264- 			// Currently, we just drop the datagram. 
265- 			// https://www.rfc-editor.org/rfc/rfc9000.html#section-5.2.2-5 
266- 			return 
267- 		}
247+ 		// TODO: Move this branch into a separate goroutine to avoid blocking 
248+ 		// the listener while processing packets. 
249+ 		l .handleUnknownDestinationDatagram (m )
250+ 		return 
268251	}
269252
270253	// TODO: This can block the listener while waiting for the conn to accept the dgram. 
271254	// Think about buffering between the receive loop and the conn. 
272255	c .sendMsg (m )
273256}
274257
258+ func  (l  * Listener ) handleUnknownDestinationDatagram (m  * datagram ) {
259+ 	defer  func () {
260+ 		if  m  !=  nil  {
261+ 			m .recycle ()
262+ 		}
263+ 	}()
264+ 	if  len (m .b ) <  minimumClientInitialDatagramSize  {
265+ 		return 
266+ 	}
267+ 	p , ok  :=  parseGenericLongHeaderPacket (m .b )
268+ 	if  ! ok  {
269+ 		// Not a long header packet, or not parseable. 
270+ 		// Short header (1-RTT) packets don't contain enough information 
271+ 		// to do anything useful with if we don't recognize the 
272+ 		// connection ID. 
273+ 		return 
274+ 	}
275+ 
276+ 	switch  p .version  {
277+ 	case  quicVersion1 :
278+ 	case  0 :
279+ 		// Version Negotiation for an unknown connection. 
280+ 		return 
281+ 	default :
282+ 		// Unknown version. 
283+ 		l .sendVersionNegotiation (p , m .addr )
284+ 		return 
285+ 	}
286+ 	if  getPacketType (m .b ) !=  packetTypeInitial  {
287+ 		// This packet isn't trying to create a new connection. 
288+ 		// It might be associated with some connection we've lost state for. 
289+ 		// TODO: Send a stateless reset when appropriate. 
290+ 		// https://www.rfc-editor.org/rfc/rfc9000.html#section-10.3 
291+ 		return 
292+ 	}
293+ 	var  now  time.Time 
294+ 	if  l .testHooks  !=  nil  {
295+ 		now  =  l .testHooks .timeNow ()
296+ 	} else  {
297+ 		now  =  time .Now ()
298+ 	}
299+ 	var  err  error 
300+ 	c , err  :=  l .newConn (now , serverSide , p .dstConnID , m .addr )
301+ 	if  err  !=  nil  {
302+ 		// The accept queue is probably full. 
303+ 		// We could send a CONNECTION_CLOSE to the peer to reject the connection. 
304+ 		// Currently, we just drop the datagram. 
305+ 		// https://www.rfc-editor.org/rfc/rfc9000.html#section-5.2.2-5 
306+ 		return 
307+ 	}
308+ 	c .sendMsg (m )
309+ 	m  =  nil  // don't recycle, sendMsg takes ownership 
310+ }
311+ 
312+ func  (l  * Listener ) sendVersionNegotiation (p  genericLongPacket , addr  netip.AddrPort ) {
313+ 	m  :=  newDatagram ()
314+ 	m .b  =  appendVersionNegotiation (m .b [:0 ], p .srcConnID , p .dstConnID , quicVersion1 )
315+ 	l .sendDatagram (m .b , addr )
316+ 	m .recycle ()
317+ }
318+ 
275319func  (l  * Listener ) sendDatagram (p  []byte , addr  netip.AddrPort ) error  {
276320	_ , err  :=  l .udpConn .WriteToUDPAddrPort (p , addr )
277321	return  err 
0 commit comments