diff options
author | Jacek Antonelli | 2009-04-30 13:04:20 -0500 |
---|---|---|
committer | Jacek Antonelli | 2009-04-30 13:07:16 -0500 |
commit | ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e (patch) | |
tree | 8348301d0ac44a524f1819b777686bf086907d76 /linden/indra/llmessage/net.cpp | |
parent | Second Life viewer sources 1.22.11 (diff) | |
download | meta-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.cpp | 113 |
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 | ||
83 | static U32 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; // Address to which datagram was sent | ||
83 | 84 | ||
84 | const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1"; | 85 | const 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 | ||
113 | LLHost get_receiving_interface() | ||
114 | { | ||
115 | return LLHost(gsnReceivingIFAddr, INVALID_PORT); | ||
116 | } | ||
117 | |||
118 | U32 get_receiving_interface_ip(void) | ||
119 | { | ||
120 | return gsnReceivingIFAddr; | ||
121 | } | ||
122 | |||
112 | const char* u32_to_ip_string(U32 ip) | 123 | const 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 | ||
521 | static 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 | |||
475 | int receive_packet(int hSocket, char * receiveBuffer) | 566 | int 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 | ||