fix: use UDP connect to probe local address (#121)

This commit is contained in:
7mile
2026-01-30 08:52:06 +08:00
committed by GitHub
parent 2a5a1f3e8a
commit 305993b013
4 changed files with 43 additions and 12 deletions

View File

@@ -377,6 +377,19 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err);
goto Cleanup;
}
// Resolve LocalAddr by RemoteAddr.
{
SOCKADDR_LEN localAddrLen;
err = getLocalAddressByUdpConnect(&RemoteAddr, AddrLen, &LocalAddr, &localAddrLen);
if (err != 0) {
Limelog("failed to resolve local addr: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err);
goto Cleanup;
}
LC_ASSERT(localAddrLen == AddrLen);
}
stage++;
LC_ASSERT(stage == STAGE_NAME_RESOLUTION);
ListenerCallbacks.stageComplete(STAGE_NAME_RESOLUTION);

View File

@@ -568,6 +568,34 @@ Exit:
return s;
}
int getLocalAddressByUdpConnect(const struct sockaddr_storage* targetAddr, SOCKADDR_LEN targetAddrLen,
struct sockaddr_storage* localAddr, SOCKADDR_LEN* localAddrLen) {
SOCKET udpSocket;
udpSocket = createSocket(targetAddr->ss_family, SOCK_DGRAM, IPPROTO_UDP, false);
if (udpSocket == INVALID_SOCKET) {
return LastSocketError();
}
if (connect(udpSocket, (struct sockaddr*)targetAddr, targetAddrLen) < 0) {
int err = LastSocketError();
Limelog("UDP connect() failed: %d\n", err);
closeSocket(udpSocket);
return err;
}
*localAddrLen = sizeof(*localAddr);
if (getsockname(udpSocket, (struct sockaddr*)localAddr, localAddrLen) < 0) {
int err = LastSocketError();
Limelog("getsockname() failed: %d\n", err);
closeSocket(udpSocket);
return err;
}
closeSocket(udpSocket);
return 0;
}
// See TCP_MAXSEG note in connectTcpSocket() above for more information.
// TCP_NODELAY must be enabled on the socket for this function to work!
int sendMtuSafe(SOCKET s, char* buffer, int size) {

View File

@@ -107,6 +107,8 @@ void addrToUrlSafeString(struct sockaddr_storage* addr, char* string, size_t str
SOCKET createSocket(int addressFamily, int socketType, int protocol, bool nonBlocking);
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec);
int getLocalAddressByUdpConnect(const struct sockaddr_storage* targetAddr, SOCKADDR_LEN targetAddrLen,
struct sockaddr_storage* localAddr, SOCKADDR_LEN* localAddrLen);
int sendMtuSafe(SOCKET s, char* buffer, int size);
SOCKET bindUdpSocket(int addressFamily, struct sockaddr_storage* localAddr, SOCKADDR_LEN addrLen, int bufferSize, int socketQosType);
int enableNoDelay(SOCKET s);

View File

@@ -477,18 +477,6 @@ static bool transactRtspMessageTcp(PRTSP_MESSAGE request, PRTSP_MESSAGE response
// Decrypt (if necessary) and deserialize the RTSP response
ret = unsealRtspMessage(responseBuffer, offset, response);
// Fetch the local address for this socket if it's not populated yet
if (LocalAddr.ss_family == 0) {
SOCKADDR_LEN addrLen = (SOCKADDR_LEN)sizeof(LocalAddr);
if (getsockname(sock, (struct sockaddr*)&LocalAddr, &addrLen) < 0) {
Limelog("Failed to get local address: %d\n", LastSocketError());
memset(&LocalAddr, 0, sizeof(LocalAddr));
}
else {
LC_ASSERT(addrLen == AddrLen);
}
}
Exit:
if (serializedMessage != NULL) {
free(serializedMessage);