aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/net.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2009-04-30 13:04:20 -0500
committerJacek Antonelli2009-04-30 13:07:16 -0500
commitca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e (patch)
tree8348301d0ac44a524f1819b777686bf086907d76 /linden/indra/llmessage/net.cpp
parentSecond Life viewer sources 1.22.11 (diff)
downloadmeta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.zip
meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.gz
meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.bz2
meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.xz
Second Life viewer sources 1.23.0-RC
Diffstat (limited to 'linden/indra/llmessage/net.cpp')
-rw-r--r--linden/indra/llmessage/net.cpp113
1 files changed, 107 insertions, 6 deletions
diff --git a/linden/indra/llmessage/net.cpp b/linden/indra/llmessage/net.cpp
index 0f0cddf..f63faa5 100644
--- a/linden/indra/llmessage/net.cpp
+++ b/linden/indra/llmessage/net.cpp
@@ -17,7 +17,8 @@
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception 20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 22 *
22 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -50,7 +51,6 @@
50#endif 51#endif
51 52
52// linden library includes 53// linden library includes
53#include "network.h"
54#include "llerror.h" 54#include "llerror.h"
55#include "llhost.h" 55#include "llhost.h"
56#include "lltimer.h" 56#include "lltimer.h"
@@ -80,6 +80,7 @@ typedef int socklen_t;
80 80
81#endif 81#endif
82 82
83static U32 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; // Address to which datagram was sent
83 84
84const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1"; 85const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1";
85 86
@@ -109,6 +110,16 @@ U32 get_sender_port()
109 return ntohs(stSrcAddr.sin_port); 110 return ntohs(stSrcAddr.sin_port);
110} 111}
111 112
113LLHost get_receiving_interface()
114{
115 return LLHost(gsnReceivingIFAddr, INVALID_PORT);
116}
117
118U32 get_receiving_interface_ip(void)
119{
120 return gsnReceivingIFAddr;
121}
122
112const char* u32_to_ip_string(U32 ip) 123const char* u32_to_ip_string(U32 ip)
113{ 124{
114 static char buffer[MAXADDRSTR]; /* Flawfinder: ignore */ 125 static char buffer[MAXADDRSTR]; /* Flawfinder: ignore */
@@ -383,11 +394,30 @@ S32 start_net(S32& socket_out, int& nPort)
383 return 1; 394 return 1;
384 } 395 }
385 396
386 // Don't bind() if we want the operating system to assign our ports for
387 // us.
388 if (NET_USE_OS_ASSIGNED_PORT == nPort) 397 if (NET_USE_OS_ASSIGNED_PORT == nPort)
389 { 398 {
390 // Do nothing; the operating system will do it for us. 399 // Although bind is not required it will tell us which port we were
400 // assigned to.
401 stLclAddr.sin_family = AF_INET;
402 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
403 stLclAddr.sin_port = htons(0);
404 llinfos << "attempting to connect on OS assigned port" << llendl;
405 nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
406 if (nRet < 0)
407 {
408 llwarns << "Failed to bind on an OS assigned port error: "
409 << nRet << llendl;
410 }
411 else
412 {
413 sockaddr_in socket_info;
414 socklen_t len = sizeof(sockaddr_in);
415 int err = getsockname(hSocket, (sockaddr*)&socket_info, &len);
416 llinfos << "Get socket returned: " << err << " length " << len << llendl;
417 nPort = ntohs(socket_info.sin_port);
418 llinfos << "Assigned port: " << nPort << llendl;
419
420 }
391 } 421 }
392 else 422 else
393 { 423 {
@@ -454,6 +484,21 @@ S32 start_net(S32& socket_out, int& nPort)
454 llinfos << "startNet - receive buffer size : " << rec_size << llendl; 484 llinfos << "startNet - receive buffer size : " << rec_size << llendl;
455 llinfos << "startNet - send buffer size : " << snd_size << llendl; 485 llinfos << "startNet - send buffer size : " << snd_size << llendl;
456 486
487#if LL_LINUX
488 // Turn on recipient address tracking
489 {
490 int use_pktinfo = 1;
491 if( setsockopt( hSocket, SOL_IP, IP_PKTINFO, &use_pktinfo, sizeof(use_pktinfo) ) == -1 )
492 {
493 llwarns << "No IP_PKTINFO available" << llendl;
494 }
495 else
496 {
497 llinfos << "IP_PKKTINFO enabled" << llendl;
498 }
499 }
500#endif
501
457 // Setup a destination address 502 // Setup a destination address
458 char achMCAddr[MAXADDRSTR] = "127.0.0.1"; /* Flawfinder: ignore */ 503 char achMCAddr[MAXADDRSTR] = "127.0.0.1"; /* Flawfinder: ignore */
459 stDstAddr.sin_family = AF_INET; 504 stDstAddr.sin_family = AF_INET;
@@ -472,6 +517,52 @@ void end_net(S32& socket_out)
472 } 517 }
473} 518}
474 519
520#if LL_LINUX
521static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *from, socklen_t *fromlen, U32 *dstip )
522{
523 int size;
524 struct iovec iov[1];
525 char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
526 struct cmsghdr *cmsgptr;
527 struct msghdr msg = {0};
528
529 iov[0].iov_base = buf;
530 iov[0].iov_len = len;
531
532 memset( &msg, 0, sizeof msg );
533 msg.msg_name = from;
534 msg.msg_namelen = *fromlen;
535 msg.msg_iov = iov;
536 msg.msg_iovlen = 1;
537 msg.msg_control = &cmsg;
538 msg.msg_controllen = sizeof(cmsg);
539
540 size = recvmsg( socket, &msg, 0 );
541
542 if( size == -1 )
543 {
544 return -1;
545 }
546
547 for( cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr ) )
548 {
549 if( cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO )
550 {
551 in_pktinfo *pktinfo = (in_pktinfo *)CMSG_DATA(cmsgptr);
552 if( pktinfo )
553 {
554 // Two choices. routed and specified. ipi_addr is routed, ipi_spec_dst is
555 // routed. We should stay with specified until we go to multiple
556 // interfaces
557 *dstip = pktinfo->ipi_spec_dst.s_addr;
558 }
559 }
560 }
561
562 return size;
563}
564#endif
565
475int receive_packet(int hSocket, char * receiveBuffer) 566int receive_packet(int hSocket, char * receiveBuffer)
476{ 567{
477 // Receives data asynchronously from the socket set by initNet(). 568 // Receives data asynchronously from the socket set by initNet().
@@ -481,7 +572,14 @@ int receive_packet(int hSocket, char * receiveBuffer)
481 int nRet; 572 int nRet;
482 socklen_t addr_size = sizeof(struct sockaddr_in); 573 socklen_t addr_size = sizeof(struct sockaddr_in);
483 574
484 nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, 0, (struct sockaddr*)&stSrcAddr, &addr_size); 575 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS;
576
577#if LL_LINUX
578 nRet = recvfrom_destip(hSocket, receiveBuffer, NET_BUFFER_SIZE, (struct sockaddr*)&stSrcAddr, &addr_size, &gsnReceivingIFAddr);
579#else
580 int recv_flags = 0;
581 nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, recv_flags, (struct sockaddr*)&stSrcAddr, &addr_size);
582#endif
485 583
486 if (nRet == -1) 584 if (nRet == -1)
487 { 585 {
@@ -489,6 +587,9 @@ int receive_packet(int hSocket, char * receiveBuffer)
489 return 0; 587 return 0;
490 } 588 }
491 589
590 // Uncomment for testing if/when implementing for Mac or Windows:
591 // llinfos << "Received datagram to in addr " << u32_to_ip_string(get_receiving_interface_ip()) << llendl;
592
492 return nRet; 593 return nRet;
493} 594}
494 595