github.com/database64128/shadowsocks-go@v1.7.0/service/udp_session_mmsg.go (about) 1 //go:build linux || netbsd 2 3 package service 4 5 import ( 6 "bytes" 7 "errors" 8 "net/netip" 9 "os" 10 "sync/atomic" 11 "time" 12 "unsafe" 13 14 "github.com/database64128/shadowsocks-go/conn" 15 "github.com/database64128/shadowsocks-go/router" 16 "github.com/database64128/shadowsocks-go/zerocopy" 17 "go.uber.org/zap" 18 "golang.org/x/sys/unix" 19 ) 20 21 // sessionUplinkMmsg is used for passing information about relay uplink to the relay goroutine. 22 type sessionUplinkMmsg struct { 23 csid uint64 24 natConn *conn.MmsgWConn 25 natConnSendCh <-chan *sessionQueuedPacket 26 natConnPacker zerocopy.ClientPacker 27 username string 28 } 29 30 // sessionDownlinkMmsg is used for passing information about relay downlink to the relay goroutine. 31 type sessionDownlinkMmsg struct { 32 csid uint64 33 clientAddrInfop *sessionClientAddrInfo 34 clientAddrInfo *atomic.Pointer[sessionClientAddrInfo] 35 natConn *conn.MmsgRConn 36 natConnRecvBufSize int 37 natConnUnpacker zerocopy.ClientUnpacker 38 serverConn *conn.MmsgWConn 39 serverConnPacker zerocopy.ServerPacker 40 username string 41 } 42 43 func (s *UDPSessionRelay) setStartFunc(batchMode string) { 44 switch batchMode { 45 case "sendmmsg", "": 46 s.startFunc = s.startMmsg 47 default: 48 s.startFunc = s.startGeneric 49 } 50 } 51 52 func (s *UDPSessionRelay) startMmsg() error { 53 serverConn, err := conn.ListenUDPRawConn(s.serverConnListenConfig, "udp", s.listenAddress) 54 if err != nil { 55 return err 56 } 57 s.serverConn = serverConn.UDPConn 58 59 s.mwg.Add(1) 60 61 go func() { 62 s.recvFromServerConnRecvmmsg(serverConn.RConn()) 63 s.mwg.Done() 64 }() 65 66 s.logger.Info("Started UDP session relay service", 67 zap.String("server", s.serverName), 68 zap.String("listenAddress", s.listenAddress), 69 ) 70 71 return nil 72 } 73 74 func (s *UDPSessionRelay) recvFromServerConnRecvmmsg(serverConn *conn.MmsgRConn) { 75 n := s.serverRecvBatchSize 76 qpvec := make([]*sessionQueuedPacket, n) 77 namevec := make([]unix.RawSockaddrInet6, n) 78 iovec := make([]unix.Iovec, n) 79 cmsgvec := make([][]byte, n) 80 msgvec := make([]conn.Mmsghdr, n) 81 82 for i := range msgvec { 83 cmsgBuf := make([]byte, conn.SocketControlMessageBufferSize) 84 cmsgvec[i] = cmsgBuf 85 msgvec[i].Msghdr.Name = (*byte)(unsafe.Pointer(&namevec[i])) 86 msgvec[i].Msghdr.Namelen = unix.SizeofSockaddrInet6 87 msgvec[i].Msghdr.Iov = &iovec[i] 88 msgvec[i].Msghdr.SetIovlen(1) 89 msgvec[i].Msghdr.Control = &cmsgBuf[0] 90 } 91 92 var ( 93 err error 94 recvmmsgCount uint64 95 packetsReceived uint64 96 payloadBytesReceived uint64 97 burstBatchSize int 98 ) 99 100 for { 101 for i := range iovec[:n] { 102 queuedPacket := s.getQueuedPacket() 103 qpvec[i] = queuedPacket 104 iovec[i].Base = &queuedPacket.buf[s.packetBufFrontHeadroom] 105 iovec[i].SetLen(s.packetBufRecvSize) 106 msgvec[i].Msghdr.SetControllen(conn.SocketControlMessageBufferSize) 107 } 108 109 n, err = serverConn.ReadMsgs(msgvec, 0) 110 if err != nil { 111 if errors.Is(err, os.ErrDeadlineExceeded) { 112 break 113 } 114 115 s.logger.Warn("Failed to batch read packets from serverConn", 116 zap.String("server", s.serverName), 117 zap.String("listenAddress", s.listenAddress), 118 zap.Error(err), 119 ) 120 121 n = 1 122 s.putQueuedPacket(qpvec[0]) 123 continue 124 } 125 126 recvmmsgCount++ 127 packetsReceived += uint64(n) 128 if burstBatchSize < n { 129 burstBatchSize = n 130 } 131 132 s.server.Lock() 133 134 msgvecn := msgvec[:n] 135 136 for i := range msgvecn { 137 msg := &msgvecn[i] 138 queuedPacket := qpvec[i] 139 140 if msg.Msghdr.Controllen == 0 { 141 s.logger.Warn("Skipping packet with no control message from serverConn", 142 zap.String("server", s.serverName), 143 zap.String("listenAddress", s.listenAddress), 144 ) 145 146 s.putQueuedPacket(queuedPacket) 147 continue 148 } 149 150 queuedPacket.clientAddrPort, err = conn.SockaddrToAddrPort(msg.Msghdr.Name, msg.Msghdr.Namelen) 151 if err != nil { 152 s.logger.Warn("Failed to parse sockaddr of packet from serverConn", 153 zap.String("server", s.serverName), 154 zap.String("listenAddress", s.listenAddress), 155 zap.Error(err), 156 ) 157 158 s.putQueuedPacket(queuedPacket) 159 continue 160 } 161 162 err = conn.ParseFlagsForError(int(msg.Msghdr.Flags)) 163 if err != nil { 164 s.logger.Warn("Packet from serverConn discarded", 165 zap.String("server", s.serverName), 166 zap.String("listenAddress", s.listenAddress), 167 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 168 zap.Uint32("packetLength", msg.Msglen), 169 zap.Error(err), 170 ) 171 172 s.putQueuedPacket(queuedPacket) 173 continue 174 } 175 176 packet := queuedPacket.buf[s.packetBufFrontHeadroom : s.packetBufFrontHeadroom+int(msg.Msglen)] 177 178 csid, err := s.server.SessionInfo(packet) 179 if err != nil { 180 s.logger.Warn("Failed to extract session info from packet", 181 zap.String("server", s.serverName), 182 zap.String("listenAddress", s.listenAddress), 183 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 184 zap.Uint32("packetLength", msg.Msglen), 185 zap.Error(err), 186 ) 187 188 s.putQueuedPacket(queuedPacket) 189 continue 190 } 191 192 entry, ok := s.table[csid] 193 if !ok { 194 entry = &session{} 195 196 entry.serverConnUnpacker, entry.username, err = s.server.NewUnpacker(packet, csid) 197 if err != nil { 198 s.logger.Warn("Failed to create unpacker for client session", 199 zap.String("server", s.serverName), 200 zap.String("listenAddress", s.listenAddress), 201 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 202 zap.Uint64("clientSessionID", csid), 203 zap.Uint32("packetLength", msg.Msglen), 204 zap.Error(err), 205 ) 206 207 s.putQueuedPacket(queuedPacket) 208 continue 209 } 210 } 211 212 queuedPacket.targetAddr, queuedPacket.start, queuedPacket.length, err = entry.serverConnUnpacker.UnpackInPlace(queuedPacket.buf, queuedPacket.clientAddrPort, s.packetBufFrontHeadroom, int(msg.Msglen)) 213 if err != nil { 214 s.logger.Warn("Failed to unpack packet from serverConn", 215 zap.String("server", s.serverName), 216 zap.String("listenAddress", s.listenAddress), 217 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 218 zap.String("username", entry.username), 219 zap.Uint64("clientSessionID", csid), 220 zap.Uint32("packetLength", msg.Msglen), 221 zap.Error(err), 222 ) 223 224 s.putQueuedPacket(queuedPacket) 225 continue 226 } 227 228 payloadBytesReceived += uint64(queuedPacket.length) 229 230 var clientAddrInfop *sessionClientAddrInfo 231 cmsg := cmsgvec[i][:msg.Msghdr.Controllen] 232 233 updateClientAddrPort := entry.clientAddrPortCache != queuedPacket.clientAddrPort 234 updateClientPktinfo := !bytes.Equal(entry.clientPktinfoCache, cmsg) 235 236 if updateClientAddrPort { 237 entry.clientAddrPortCache = queuedPacket.clientAddrPort 238 } 239 240 if updateClientPktinfo { 241 entry.clientPktinfoCache = make([]byte, len(cmsg)) 242 copy(entry.clientPktinfoCache, cmsg) 243 } 244 245 if updateClientAddrPort || updateClientPktinfo { 246 clientPktinfoAddr, clientPktinfoIfindex, err := conn.ParsePktinfoCmsg(cmsg) 247 if err != nil { 248 s.logger.Warn("Failed to parse pktinfo control message from serverConn", 249 zap.String("server", s.serverName), 250 zap.String("listenAddress", s.listenAddress), 251 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 252 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 253 zap.String("username", entry.username), 254 zap.Uint64("clientSessionID", csid), 255 zap.Error(err), 256 ) 257 258 s.putQueuedPacket(queuedPacket) 259 continue 260 } 261 262 clientAddrInfop = &sessionClientAddrInfo{entry.clientAddrPortCache, entry.clientPktinfoCache} 263 entry.clientAddrInfo.Store(clientAddrInfop) 264 265 if ce := s.logger.Check(zap.DebugLevel, "Updated client address info"); ce != nil { 266 ce.Write( 267 zap.String("server", s.serverName), 268 zap.String("listenAddress", s.listenAddress), 269 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 270 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 271 zap.Stringer("clientPktinfoAddr", clientPktinfoAddr), 272 zap.Uint32("clientPktinfoIfindex", clientPktinfoIfindex), 273 zap.String("username", entry.username), 274 zap.Uint64("clientSessionID", csid), 275 ) 276 } 277 } 278 279 if !ok { 280 natConnSendCh := make(chan *sessionQueuedPacket, s.sendChannelCapacity) 281 entry.natConnSendCh = natConnSendCh 282 s.table[csid] = entry 283 284 go func() { 285 var sendChClean bool 286 287 defer func() { 288 s.server.Lock() 289 close(natConnSendCh) 290 delete(s.table, csid) 291 s.server.Unlock() 292 293 if !sendChClean { 294 for queuedPacket := range natConnSendCh { 295 s.putQueuedPacket(queuedPacket) 296 } 297 } 298 }() 299 300 c, err := s.router.GetUDPClient(router.RequestInfo{ 301 ServerIndex: s.serverIndex, 302 Username: entry.username, 303 SourceAddrPort: queuedPacket.clientAddrPort, 304 TargetAddr: queuedPacket.targetAddr, 305 }) 306 if err != nil { 307 s.logger.Warn("Failed to get UDP client for new NAT session", 308 zap.String("server", s.serverName), 309 zap.String("listenAddress", s.listenAddress), 310 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 311 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 312 zap.String("username", entry.username), 313 zap.Uint64("clientSessionID", csid), 314 zap.Error(err), 315 ) 316 return 317 } 318 319 // Only add for the current goroutine here, since we don't want the router to block exiting. 320 s.wg.Add(1) 321 defer s.wg.Done() 322 323 clientInfo, natConnPacker, natConnUnpacker, err := c.NewSession() 324 if err != nil { 325 s.logger.Warn("Failed to create new UDP client session", 326 zap.String("server", s.serverName), 327 zap.String("client", clientInfo.Name), 328 zap.String("listenAddress", s.listenAddress), 329 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 330 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 331 zap.String("username", entry.username), 332 zap.Uint64("clientSessionID", csid), 333 zap.Error(err), 334 ) 335 return 336 } 337 338 serverConnPacker, err := entry.serverConnUnpacker.NewPacker() 339 if err != nil { 340 s.logger.Warn("Failed to create packer for client session", 341 zap.String("server", s.serverName), 342 zap.String("client", clientInfo.Name), 343 zap.String("listenAddress", s.listenAddress), 344 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 345 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 346 zap.String("username", entry.username), 347 zap.Uint64("clientSessionID", csid), 348 zap.Error(err), 349 ) 350 return 351 } 352 353 natConn, err := conn.ListenUDPRawConn(clientInfo.ListenConfig, "udp", "") 354 if err != nil { 355 s.logger.Warn("Failed to create UDP socket for new NAT session", 356 zap.String("server", s.serverName), 357 zap.String("client", clientInfo.Name), 358 zap.String("listenAddress", s.listenAddress), 359 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 360 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 361 zap.String("username", entry.username), 362 zap.Uint64("clientSessionID", csid), 363 zap.Error(err), 364 ) 365 return 366 } 367 368 err = natConn.SetReadDeadline(time.Now().Add(s.natTimeout)) 369 if err != nil { 370 s.logger.Warn("Failed to set read deadline on natConn", 371 zap.String("server", s.serverName), 372 zap.String("client", clientInfo.Name), 373 zap.String("listenAddress", s.listenAddress), 374 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 375 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 376 zap.Duration("natTimeout", s.natTimeout), 377 zap.String("username", entry.username), 378 zap.Uint64("clientSessionID", csid), 379 zap.Error(err), 380 ) 381 natConn.Close() 382 return 383 } 384 385 oldState := entry.state.Swap(natConn.UDPConn) 386 if oldState != nil { 387 natConn.Close() 388 return 389 } 390 391 // No more early returns! 392 sendChClean = true 393 394 s.logger.Info("UDP session relay started", 395 zap.String("server", s.serverName), 396 zap.String("client", clientInfo.Name), 397 zap.String("listenAddress", s.listenAddress), 398 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 399 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 400 zap.String("username", entry.username), 401 zap.Uint64("clientSessionID", csid), 402 ) 403 404 s.wg.Add(1) 405 406 go func() { 407 s.relayServerConnToNatConnSendmmsg(sessionUplinkMmsg{ 408 csid: csid, 409 natConn: natConn.WConn(), 410 natConnSendCh: natConnSendCh, 411 natConnPacker: natConnPacker, 412 username: entry.username, 413 }) 414 natConn.Close() 415 s.wg.Done() 416 }() 417 418 s.relayNatConnToServerConnSendmmsg(sessionDownlinkMmsg{ 419 csid: csid, 420 clientAddrInfop: clientAddrInfop, 421 clientAddrInfo: &entry.clientAddrInfo, 422 natConn: natConn.RConn(), 423 natConnRecvBufSize: clientInfo.MaxPacketSize, 424 natConnUnpacker: natConnUnpacker, 425 serverConn: serverConn.WConn(), 426 serverConnPacker: serverConnPacker, 427 username: entry.username, 428 }) 429 }() 430 431 if ce := s.logger.Check(zap.DebugLevel, "New UDP session"); ce != nil { 432 ce.Write( 433 zap.String("server", s.serverName), 434 zap.String("listenAddress", s.listenAddress), 435 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 436 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 437 zap.String("username", entry.username), 438 zap.Uint64("clientSessionID", csid), 439 ) 440 } 441 } 442 443 select { 444 case entry.natConnSendCh <- queuedPacket: 445 default: 446 if ce := s.logger.Check(zap.DebugLevel, "Dropping packet due to full send channel"); ce != nil { 447 ce.Write( 448 zap.String("server", s.serverName), 449 zap.String("listenAddress", s.listenAddress), 450 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 451 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 452 zap.String("username", entry.username), 453 zap.Uint64("clientSessionID", csid), 454 ) 455 } 456 457 s.putQueuedPacket(queuedPacket) 458 } 459 } 460 461 s.server.Unlock() 462 } 463 464 for i := range qpvec { 465 s.putQueuedPacket(qpvec[i]) 466 } 467 468 s.logger.Info("Finished receiving from serverConn", 469 zap.String("server", s.serverName), 470 zap.String("listenAddress", s.listenAddress), 471 zap.Uint64("recvmmsgCount", recvmmsgCount), 472 zap.Uint64("packetsReceived", packetsReceived), 473 zap.Uint64("payloadBytesReceived", payloadBytesReceived), 474 zap.Int("burstBatchSize", burstBatchSize), 475 ) 476 } 477 478 func (s *UDPSessionRelay) relayServerConnToNatConnSendmmsg(uplink sessionUplinkMmsg) { 479 var ( 480 destAddrPort netip.AddrPort 481 packetStart int 482 packetLength int 483 err error 484 sendmmsgCount uint64 485 packetsSent uint64 486 payloadBytesSent uint64 487 burstBatchSize int 488 ) 489 490 qpvec := make([]*sessionQueuedPacket, s.relayBatchSize) 491 namevec := make([]unix.RawSockaddrInet6, s.relayBatchSize) 492 iovec := make([]unix.Iovec, s.relayBatchSize) 493 msgvec := make([]conn.Mmsghdr, s.relayBatchSize) 494 495 for i := range msgvec { 496 msgvec[i].Msghdr.Name = (*byte)(unsafe.Pointer(&namevec[i])) 497 msgvec[i].Msghdr.Namelen = unix.SizeofSockaddrInet6 498 msgvec[i].Msghdr.Iov = &iovec[i] 499 msgvec[i].Msghdr.SetIovlen(1) 500 } 501 502 main: 503 for { 504 var count int 505 506 // Block on first dequeue op. 507 queuedPacket, ok := <-uplink.natConnSendCh 508 if !ok { 509 break 510 } 511 512 dequeue: 513 for { 514 destAddrPort, packetStart, packetLength, err = uplink.natConnPacker.PackInPlace(queuedPacket.buf, queuedPacket.targetAddr, queuedPacket.start, queuedPacket.length) 515 if err != nil { 516 s.logger.Warn("Failed to pack packet for natConn", 517 zap.String("server", s.serverName), 518 zap.String("listenAddress", s.listenAddress), 519 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 520 zap.Stringer("targetAddress", &queuedPacket.targetAddr), 521 zap.String("username", uplink.username), 522 zap.Uint64("clientSessionID", uplink.csid), 523 zap.Int("payloadLength", queuedPacket.length), 524 zap.Error(err), 525 ) 526 527 s.putQueuedPacket(queuedPacket) 528 529 if count == 0 { 530 continue main 531 } 532 goto next 533 } 534 535 qpvec[count] = queuedPacket 536 namevec[count] = conn.AddrPortToSockaddrInet6(destAddrPort) 537 iovec[count].Base = &queuedPacket.buf[packetStart] 538 iovec[count].SetLen(packetLength) 539 count++ 540 payloadBytesSent += uint64(queuedPacket.length) 541 542 if count == s.relayBatchSize { 543 break 544 } 545 546 next: 547 select { 548 case queuedPacket, ok = <-uplink.natConnSendCh: 549 if !ok { 550 break dequeue 551 } 552 default: 553 break dequeue 554 } 555 } 556 557 if err := uplink.natConn.WriteMsgs(msgvec[:count], 0); err != nil { 558 s.logger.Warn("Failed to batch write packets to natConn", 559 zap.String("server", s.serverName), 560 zap.String("listenAddress", s.listenAddress), 561 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 562 zap.Stringer("lastTargetAddress", &qpvec[count-1].targetAddr), 563 zap.Stringer("lastWriteDestAddress", destAddrPort), 564 zap.String("username", uplink.username), 565 zap.Uint64("clientSessionID", uplink.csid), 566 zap.Error(err), 567 ) 568 } 569 570 if err := uplink.natConn.SetReadDeadline(time.Now().Add(s.natTimeout)); err != nil { 571 s.logger.Warn("Failed to set read deadline on natConn", 572 zap.String("server", s.serverName), 573 zap.String("listenAddress", s.listenAddress), 574 zap.Stringer("clientAddress", &queuedPacket.clientAddrPort), 575 zap.Duration("natTimeout", s.natTimeout), 576 zap.String("username", uplink.username), 577 zap.Uint64("clientSessionID", uplink.csid), 578 zap.Error(err), 579 ) 580 } 581 582 sendmmsgCount++ 583 packetsSent += uint64(count) 584 if burstBatchSize < count { 585 burstBatchSize = count 586 } 587 588 qpvecn := qpvec[:count] 589 590 for i := range qpvecn { 591 s.putQueuedPacket(qpvecn[i]) 592 } 593 594 if !ok { 595 break 596 } 597 } 598 599 s.logger.Info("Finished relay serverConn -> natConn", 600 zap.String("server", s.serverName), 601 zap.String("listenAddress", s.listenAddress), 602 zap.Stringer("lastWriteDestAddress", destAddrPort), 603 zap.String("username", uplink.username), 604 zap.Uint64("clientSessionID", uplink.csid), 605 zap.Uint64("sendmmsgCount", sendmmsgCount), 606 zap.Uint64("packetsSent", packetsSent), 607 zap.Uint64("payloadBytesSent", payloadBytesSent), 608 zap.Int("burstBatchSize", burstBatchSize), 609 ) 610 611 s.collector.CollectUDPSessionUplink(uplink.username, packetsSent, payloadBytesSent) 612 } 613 614 func (s *UDPSessionRelay) relayNatConnToServerConnSendmmsg(downlink sessionDownlinkMmsg) { 615 clientAddrInfop := downlink.clientAddrInfop 616 clientAddrPort := downlink.clientAddrInfop.addrPort 617 clientPktinfo := downlink.clientAddrInfop.pktinfo 618 maxClientPacketSize := zerocopy.MaxPacketSizeForAddr(s.mtu, clientAddrPort.Addr()) 619 620 serverConnPackerInfo := downlink.serverConnPacker.ServerPackerInfo() 621 natConnUnpackerInfo := downlink.natConnUnpacker.ClientUnpackerInfo() 622 headroom := zerocopy.UDPRelayHeadroom(serverConnPackerInfo.Headroom, natConnUnpackerInfo.Headroom) 623 624 var ( 625 sendmmsgCount uint64 626 packetsSent uint64 627 payloadBytesSent uint64 628 burstBatchSize int 629 ) 630 631 rsa6, namelen := conn.AddrPortToSockaddrValue(clientAddrPort) 632 savec := make([]unix.RawSockaddrInet6, s.relayBatchSize) 633 bufvec := make([][]byte, s.relayBatchSize) 634 riovec := make([]unix.Iovec, s.relayBatchSize) 635 siovec := make([]unix.Iovec, s.relayBatchSize) 636 rmsgvec := make([]conn.Mmsghdr, s.relayBatchSize) 637 smsgvec := make([]conn.Mmsghdr, s.relayBatchSize) 638 639 for i := 0; i < s.relayBatchSize; i++ { 640 packetBuf := make([]byte, headroom.Front+downlink.natConnRecvBufSize+headroom.Rear) 641 bufvec[i] = packetBuf 642 643 riovec[i].Base = &packetBuf[headroom.Front] 644 riovec[i].SetLen(downlink.natConnRecvBufSize) 645 646 rmsgvec[i].Msghdr.Name = (*byte)(unsafe.Pointer(&savec[i])) 647 rmsgvec[i].Msghdr.Namelen = unix.SizeofSockaddrInet6 648 rmsgvec[i].Msghdr.Iov = &riovec[i] 649 rmsgvec[i].Msghdr.SetIovlen(1) 650 651 smsgvec[i].Msghdr.Name = (*byte)(unsafe.Pointer(&rsa6)) 652 smsgvec[i].Msghdr.Namelen = namelen 653 smsgvec[i].Msghdr.Iov = &siovec[i] 654 smsgvec[i].Msghdr.SetIovlen(1) 655 smsgvec[i].Msghdr.Control = &clientPktinfo[0] 656 smsgvec[i].Msghdr.SetControllen(len(clientPktinfo)) 657 } 658 659 for { 660 nr, err := downlink.natConn.ReadMsgs(rmsgvec, 0) 661 if err != nil { 662 if errors.Is(err, os.ErrDeadlineExceeded) { 663 break 664 } 665 666 s.logger.Warn("Failed to batch read packets from natConn", 667 zap.String("server", s.serverName), 668 zap.String("listenAddress", s.listenAddress), 669 zap.Stringer("clientAddress", clientAddrPort), 670 zap.String("username", downlink.username), 671 zap.Uint64("clientSessionID", downlink.csid), 672 zap.Error(err), 673 ) 674 continue 675 } 676 677 if caip := downlink.clientAddrInfo.Load(); caip != clientAddrInfop { 678 clientAddrInfop = caip 679 clientAddrPort = caip.addrPort 680 clientPktinfo = caip.pktinfo 681 maxClientPacketSize = zerocopy.MaxPacketSizeForAddr(s.mtu, clientAddrPort.Addr()) 682 rsa6, _ = conn.AddrPortToSockaddrValue(clientAddrPort) // namelen won't change 683 684 for i := range smsgvec { 685 smsgvec[i].Msghdr.Control = &clientPktinfo[0] 686 smsgvec[i].Msghdr.SetControllen(len(clientPktinfo)) 687 } 688 } 689 690 var ns int 691 rmsgvecn := rmsgvec[:nr] 692 693 for i := range rmsgvecn { 694 msg := &rmsgvecn[i] 695 696 packetSourceAddrPort, err := conn.SockaddrToAddrPort(msg.Msghdr.Name, msg.Msghdr.Namelen) 697 if err != nil { 698 s.logger.Warn("Failed to parse sockaddr of packet from natConn", 699 zap.String("server", s.serverName), 700 zap.String("listenAddress", s.listenAddress), 701 zap.Stringer("clientAddress", clientAddrPort), 702 zap.String("username", downlink.username), 703 zap.Uint64("clientSessionID", downlink.csid), 704 zap.Error(err), 705 ) 706 continue 707 } 708 709 err = conn.ParseFlagsForError(int(msg.Msghdr.Flags)) 710 if err != nil { 711 s.logger.Warn("Failed to read packet from natConn", 712 zap.String("server", s.serverName), 713 zap.String("listenAddress", s.listenAddress), 714 zap.Stringer("clientAddress", clientAddrPort), 715 zap.Stringer("packetSourceAddress", packetSourceAddrPort), 716 zap.String("username", downlink.username), 717 zap.Uint64("clientSessionID", downlink.csid), 718 zap.Uint32("packetLength", msg.Msglen), 719 zap.Error(err), 720 ) 721 continue 722 } 723 724 packetBuf := bufvec[i] 725 726 payloadSourceAddrPort, payloadStart, payloadLength, err := downlink.natConnUnpacker.UnpackInPlace(packetBuf, packetSourceAddrPort, headroom.Front, int(msg.Msglen)) 727 if err != nil { 728 s.logger.Warn("Failed to unpack packet from natConn", 729 zap.String("server", s.serverName), 730 zap.String("listenAddress", s.listenAddress), 731 zap.Stringer("clientAddress", clientAddrPort), 732 zap.Stringer("packetSourceAddress", packetSourceAddrPort), 733 zap.String("username", downlink.username), 734 zap.Uint64("clientSessionID", downlink.csid), 735 zap.Uint32("packetLength", msg.Msglen), 736 zap.Error(err), 737 ) 738 continue 739 } 740 741 packetStart, packetLength, err := downlink.serverConnPacker.PackInPlace(packetBuf, payloadSourceAddrPort, payloadStart, payloadLength, maxClientPacketSize) 742 if err != nil { 743 s.logger.Warn("Failed to pack packet for serverConn", 744 zap.String("server", s.serverName), 745 zap.String("listenAddress", s.listenAddress), 746 zap.Stringer("clientAddress", clientAddrPort), 747 zap.Stringer("packetSourceAddress", packetSourceAddrPort), 748 zap.Stringer("payloadSourceAddress", payloadSourceAddrPort), 749 zap.String("username", downlink.username), 750 zap.Uint64("clientSessionID", downlink.csid), 751 zap.Int("payloadLength", payloadLength), 752 zap.Int("maxClientPacketSize", maxClientPacketSize), 753 zap.Error(err), 754 ) 755 continue 756 } 757 758 siovec[ns].Base = &packetBuf[packetStart] 759 siovec[ns].SetLen(packetLength) 760 ns++ 761 payloadBytesSent += uint64(payloadLength) 762 } 763 764 if ns == 0 { 765 continue 766 } 767 768 err = downlink.serverConn.WriteMsgs(smsgvec[:ns], 0) 769 if err != nil { 770 s.logger.Warn("Failed to batch write packets to serverConn", 771 zap.String("server", s.serverName), 772 zap.String("listenAddress", s.listenAddress), 773 zap.Stringer("clientAddress", clientAddrPort), 774 zap.String("username", downlink.username), 775 zap.Uint64("clientSessionID", downlink.csid), 776 zap.Error(err), 777 ) 778 } 779 780 sendmmsgCount++ 781 packetsSent += uint64(ns) 782 if burstBatchSize < ns { 783 burstBatchSize = ns 784 } 785 } 786 787 s.logger.Info("Finished relay serverConn <- natConn", 788 zap.String("server", s.serverName), 789 zap.String("listenAddress", s.listenAddress), 790 zap.Stringer("clientAddress", clientAddrPort), 791 zap.String("username", downlink.username), 792 zap.Uint64("clientSessionID", downlink.csid), 793 zap.Uint64("sendmmsgCount", sendmmsgCount), 794 zap.Uint64("packetsSent", packetsSent), 795 zap.Uint64("payloadBytesSent", payloadBytesSent), 796 zap.Int("burstBatchSize", burstBatchSize), 797 ) 798 799 s.collector.CollectUDPSessionDownlink(downlink.username, packetsSent, payloadBytesSent) 800 }