diff options
author | Robert Knop <prospero@lindenlab.com> | 2009-01-19 22:05:19 +0000 |
---|---|---|
committer | Robert Knop <prospero@lindenlab.com> | 2009-01-19 22:05:19 +0000 |
commit | ce888706c5589bbd30423cd1cbfb7b168b16d680 (patch) | |
tree | 9869898ee1d915bfc6faec72a5c9f5198702f2df /indra/llmessage/net.cpp | |
parent | f1380f2fc3eecd8dfd2f75d053ff86716d5055f7 (diff) |
svn merge -r108236:108243 svn+ssh://svn.lindenlab.com/svn/linden/branches/server/server-1.25
Still merging from server-1.25... one day I will catch up!
No conflicts
Diffstat (limited to 'indra/llmessage/net.cpp')
-rw-r--r-- | indra/llmessage/net.cpp | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 4f2242fe52..94a0feb6a7 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -71,6 +71,7 @@ static WSADATA stWSAData; struct sockaddr_in stDstAddr; struct sockaddr_in stSrcAddr; struct sockaddr_in stLclAddr; +static U32 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; // Address to which datagram was sent #if LL_DARWIN #ifndef _SOCKLEN_T @@ -110,6 +111,16 @@ U32 get_sender_port() return ntohs(stSrcAddr.sin_port); } +LLHost get_receiving_interface() +{ + return LLHost(gsnReceivingIFAddr, INVALID_PORT); +} + +U32 get_receiving_interface_ip(void) +{ + return gsnReceivingIFAddr; +} + const char* u32_to_ip_string(U32 ip) { static char buffer[MAXADDRSTR]; /* Flawfinder: ignore */ @@ -455,6 +466,21 @@ S32 start_net(S32& socket_out, int& nPort) llinfos << "startNet - receive buffer size : " << rec_size << llendl; llinfos << "startNet - send buffer size : " << snd_size << llendl; +#if LL_LINUX + // Turn on recipient address tracking + { + int use_pktinfo = 1; + if( setsockopt( hSocket, SOL_IP, IP_PKTINFO, &use_pktinfo, sizeof(use_pktinfo) ) == -1 ) + { + llwarns << "No IP_PKTINFO available" << llendl; + } + else + { + llinfos << "IP_PKKTINFO enabled" << llendl; + } + } +#endif + // Setup a destination address char achMCAddr[MAXADDRSTR] = "127.0.0.1"; /* Flawfinder: ignore */ stDstAddr.sin_family = AF_INET; @@ -473,6 +499,52 @@ void end_net(S32& socket_out) } } +#if LL_LINUX +static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *from, socklen_t *fromlen, U32 *dstip ) +{ + int size; + struct iovec iov[1]; + char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))]; + struct cmsghdr *cmsgptr; + struct msghdr msg = {0}; + + iov[0].iov_base = buf; + iov[0].iov_len = len; + + memset( &msg, 0, sizeof msg ); + msg.msg_name = from; + msg.msg_namelen = *fromlen; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = &cmsg; + msg.msg_controllen = sizeof(cmsg); + + size = recvmsg( socket, &msg, 0 ); + + if( size == -1 ) + { + return -1; + } + + for( cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr ) ) + { + if( cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO ) + { + in_pktinfo *pktinfo = (in_pktinfo *)CMSG_DATA(cmsgptr); + if( pktinfo ) + { + // Two choices. routed and specified. ipi_addr is routed, ipi_spec_dst is + // routed. We should stay with specified until we go to multiple + // interfaces + *dstip = pktinfo->ipi_spec_dst.s_addr; + } + } + } + + return size; +} +#endif + int receive_packet(int hSocket, char * receiveBuffer) { // Receives data asynchronously from the socket set by initNet(). @@ -482,7 +554,14 @@ int receive_packet(int hSocket, char * receiveBuffer) int nRet; socklen_t addr_size = sizeof(struct sockaddr_in); - nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, 0, (struct sockaddr*)&stSrcAddr, &addr_size); + gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; + +#if LL_LINUX + nRet = recvfrom_destip(hSocket, receiveBuffer, NET_BUFFER_SIZE, (struct sockaddr*)&stSrcAddr, &addr_size, &gsnReceivingIFAddr); +#else + int recv_flags = 0; + nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, recv_flags, (struct sockaddr*)&stSrcAddr, &addr_size); +#endif if (nRet == -1) { @@ -490,6 +569,9 @@ int receive_packet(int hSocket, char * receiveBuffer) return 0; } + // Uncomment for testing if/when implementing for Mac or Windows: + // llinfos << "Received datagram to in addr " << u32_to_ip_string(get_receiving_interface_ip()) << llendl; + return nRet; } |