(req *request)
| 293 | } |
| 294 | |
| 295 | func (s *Server) handleAssociate(req *request) error { |
| 296 | destinationAddr := req.DestinationAddr.String() |
| 297 | udpConn, err := s.ProxyListenPacket(s.Context, "udp", destinationAddr) |
| 298 | if err != nil { |
| 299 | if err := sendReply(req.Conn, errToReply(err), nil); err != nil { |
| 300 | return fmt.Errorf("failed to send reply: %v", err) |
| 301 | } |
| 302 | return fmt.Errorf("connect to %v failed: %w", req.DestinationAddr, err) |
| 303 | } |
| 304 | |
| 305 | ip, port, err := s.PacketForwardAddress(s.Context, destinationAddr, udpConn, req.Conn) |
| 306 | if err != nil { |
| 307 | return err |
| 308 | } |
| 309 | bind := address{IP: ip, Port: port} |
| 310 | if err := sendReply(req.Conn, successReply, &bind); err != nil { |
| 311 | return fmt.Errorf("failed to send reply: %v", err) |
| 312 | } |
| 313 | |
| 314 | if s.UserAssociateHandle == nil { |
| 315 | return s.embedHandleAssociate(req, udpConn) |
| 316 | } |
| 317 | |
| 318 | cConn := &udpCustomConn{ |
| 319 | PacketConn: udpConn, |
| 320 | assocTCPConn: req.Conn, |
| 321 | frc: make(chan bool), |
| 322 | packetQueue: make(chan *readStruct), |
| 323 | } |
| 324 | |
| 325 | cConn.asyncReadPackets() |
| 326 | |
| 327 | // wait for first packet so that target sender and receiver get known |
| 328 | <-cConn.frc |
| 329 | |
| 330 | proxyReq := &statute.ProxyRequest{ |
| 331 | Conn: cConn, |
| 332 | Reader: cConn, |
| 333 | Writer: cConn, |
| 334 | Network: "udp", |
| 335 | Destination: cConn.targetAddr.String(), |
| 336 | DestHost: cConn.targetAddr.(*net.UDPAddr).IP.String(), |
| 337 | DestPort: int32(cConn.targetAddr.(*net.UDPAddr).Port), |
| 338 | } |
| 339 | |
| 340 | return s.UserAssociateHandle(proxyReq) |
| 341 | } |
| 342 | |
| 343 | func (s *Server) embedHandleAssociate(req *request, udpConn net.PacketConn) error { |
| 344 | defer func() { |
no test coverage detected