diff --git a/src/Connection.c b/src/Connection.c index d2e8292..fd5776b 100644 --- a/src/Connection.c +++ b/src/Connection.c @@ -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); diff --git a/src/PlatformSockets.c b/src/PlatformSockets.c index 56f9b9c..8468b82 100644 --- a/src/PlatformSockets.c +++ b/src/PlatformSockets.c @@ -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) { diff --git a/src/PlatformSockets.h b/src/PlatformSockets.h index 78ae4be..930f461 100644 --- a/src/PlatformSockets.h +++ b/src/PlatformSockets.h @@ -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); diff --git a/src/RtspConnection.c b/src/RtspConnection.c index d8f1b35..52ce2b1 100644 --- a/src/RtspConnection.c +++ b/src/RtspConnection.c @@ -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);