You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: udp_linux.go
    path of file: ./repos/hysteria/app/internal/tproxy
    
    the code of the file until where you have to start completion: package tproxy

import (
	"errors"
	"net"
	"time"

	"github.com/apernet/go-tproxy"
	"github.com/apernet/hysteria/core/client"
)

const (
	udpBufferSize  = 4096
	defaultTimeout = 60 * time.Second
)

type UDPTProxy struct {
	HyClient    client.Client
	Timeout     time.Duration
	EventLogger UDPEventLogger
}

type UDPEventLogger interface {
	Connect(addr, reqAddr net.Addr)
	Error(addr, reqAddr net.Addr, err error)
}

func (r *UDPTProxy) ListenAndServe(laddr *net.UDPAddr) error {
	conn, err := tproxy.ListenUDP("udp", laddr)
	if err != nil {
		return err
	}
	defer conn.Close()
	buf := make([]byte, udpBufferSize)
	for {
		// We will only get the first packet of each src/dst pair here,
	
    
func (r *UDPTProxy) forwarding(conn *net.UDPConn, hyConn client.HyUDPConn, dst string) error {
	errChan := make(chan error, 2)
	// Local <- Remote
	go func() {
		for {
			bs, _, err := hyConn.Receive()
			if err != nil {
				errChan <- err
				return
			}
			_, err = conn.Write(bs)
			if err != nil {
				errChan <- err
				return
			}
			_ = r.updateConnDeadline(conn)
		}
	}()
	// Local -> Remote
	go func() {
		buf := make([]byte, udpBufferSize)
		for {
			_ = r.updateConnDeadline(conn)
			n, err := conn.Read(buf)
			if n > 0 {
				err := hyConn.Send(buf[:n], dst)
				if err != nil {
					errChan <- err
					return
				}
			}
			if err != nil {
				errChan <- err
				return
			}
		}
	}()
	return <-errChan
}