TUN-5659: Proxy UDP with zero-byte payload
This commit is contained in:
		
							parent
							
								
									10fc450ae5
								
							
						
					
					
						commit
						c196679bc7
					
				|  | @ -106,6 +106,7 @@ func (s *Session) waitForCloseCondition(ctx context.Context, closeAfterIdle time | ||||||
| func (s *Session) dstToTransport(buffer []byte) error { | func (s *Session) dstToTransport(buffer []byte) error { | ||||||
| 	n, err := s.dstConn.Read(buffer) | 	n, err := s.dstConn.Read(buffer) | ||||||
| 	s.markActive() | 	s.markActive() | ||||||
|  | 	// https://pkg.go.dev/io#Reader suggests caller should always process n > 0 bytes
 | ||||||
| 	if n > 0 { | 	if n > 0 { | ||||||
| 		if n <= int(s.transport.MTU()) { | 		if n <= int(s.transport.MTU()) { | ||||||
| 			err = s.transport.SendTo(s.ID, buffer[:n]) | 			err = s.transport.SendTo(s.ID, buffer[:n]) | ||||||
|  | @ -118,6 +119,10 @@ func (s *Session) dstToTransport(buffer []byte) error { | ||||||
| 				Msg("dropped packet exceeding MTU") | 				Msg("dropped packet exceeding MTU") | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	// Some UDP application might send 0-size payload.
 | ||||||
|  | 	if err == nil && n == 0 { | ||||||
|  | 		err = s.transport.SendTo(s.ID, []byte{}) | ||||||
|  | 	} | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -195,3 +195,40 @@ func TestMarkActiveNotBlocking(t *testing.T) { | ||||||
| 	} | 	} | ||||||
| 	wg.Wait() | 	wg.Wait() | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestZeroBytePayload(t *testing.T) { | ||||||
|  | 	sessionID := uuid.New() | ||||||
|  | 	cfdConn, originConn := net.Pipe() | ||||||
|  | 	transport := &mockQUICTransport{ | ||||||
|  | 		reqChan:  newDatagramChannel(1), | ||||||
|  | 		respChan: newDatagramChannel(1), | ||||||
|  | 	} | ||||||
|  | 	log := zerolog.Nop() | ||||||
|  | 	session := newSession(sessionID, transport, cfdConn, &log) | ||||||
|  | 
 | ||||||
|  | 	ctx, cancel := context.WithCancel(context.Background()) | ||||||
|  | 	errGroup, ctx := errgroup.WithContext(ctx) | ||||||
|  | 	errGroup.Go(func() error { | ||||||
|  | 		// Read from underlying conn and send to transport
 | ||||||
|  | 		closedByRemote, err := session.Serve(ctx, time.Minute*2) | ||||||
|  | 		require.Equal(t, context.Canceled, err) | ||||||
|  | 		require.False(t, closedByRemote) | ||||||
|  | 		return nil | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	errGroup.Go(func() error { | ||||||
|  | 		// Write to underlying connection
 | ||||||
|  | 		n, err := originConn.Write([]byte{}) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 		require.Equal(t, 0, n) | ||||||
|  | 		return nil | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	receivedSessionID, payload, err := transport.respChan.Receive(ctx) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.Len(t, payload, 0) | ||||||
|  | 	require.Equal(t, sessionID, receivedSessionID) | ||||||
|  | 
 | ||||||
|  | 	cancel() | ||||||
|  | 	require.NoError(t, errGroup.Wait()) | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue