platformNet.cpp
Engine/source/platform/platformNet.cpp
Classes:
Namespaces:
namespace
Public Variables
const SOCKET
Public Functions
addPolledSocket(NetSocket handleFd, SOCKET fd, S32 state, char * remoteAddr, S32 port)
Vector< PolledSocket * >
gPolledSockets(__FILE__ , __LINE__ )
IPSocket6ToNetAddress(const struct sockaddr_in6 * sockAddr, NetAddress * address)
IPSocketToNetAddress(const struct sockaddr_in * sockAddr, NetAddress * address)
NetAddressToIPSocket(const NetAddress * address, struct sockaddr_in * sockAddr)
NetAddressToIPSocket6(const NetAddress * address, struct sockaddr_in6 * sockAddr)
bool
netSocketWaitForWritable(NetSocket handleFd, S32 timeoutMs)
Detailed Description
Public Variables
const SOCKET InvalidSocketHandle
Public Functions
addPolledSocket(NetSocket handleFd, SOCKET fd, S32 state, char * remoteAddr, S32 port)
gPolledSockets(__FILE__ , __LINE__ )
IPSocket6ToNetAddress(const struct sockaddr_in6 * sockAddr, NetAddress * address)
IPSocketToNetAddress(const struct sockaddr_in * sockAddr, NetAddress * address)
NetAddressToIPSocket(const NetAddress * address, struct sockaddr_in * sockAddr)
NetAddressToIPSocket6(const NetAddress * address, struct sockaddr_in6 * sockAddr)
netSocketWaitForWritable(NetSocket handleFd, S32 timeoutMs)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platformNet.h" 25#include "platform/threads/mutex.h" 26#include "core/strings/stringFunctions.h" 27#include "core/util/hashFunction.h" 28#include "console/consoleTypes.h" 29 30// jamesu - debug DNS 31//#define TORQUE_DEBUG_LOOKUPS 32 33 34#if defined (TORQUE_OS_WIN) 35#define TORQUE_USE_WINSOCK 36#include <errno.h> 37#include <ws2tcpip.h> 38 39#ifndef EINPROGRESS 40#define EINPROGRESS WSAEINPROGRESS 41#endif // EINPROGRESS 42 43#define ioctl ioctlsocket 44 45typedef S32 socklen_t; 46 47#elif defined ( TORQUE_OS_MAC ) 48 49#include <unistd.h> 50#include <sys/types.h> 51#include <sys/socket.h> 52#include <sys/poll.h> 53#include <arpa/inet.h> 54#include <netdb.h> 55#include <netinet/in.h> 56#include <errno.h> 57#include <sys/ioctl.h> 58#include <net/if.h> 59 60typedef sockaddr_in SOCKADDR_IN; 61typedef sockaddr * PSOCKADDR; 62typedef sockaddr SOCKADDR; 63typedef in_addr IN_ADDR; 64typedef int SOCKET; 65 66#define INVALID_SOCKET -1 67#define SOCKET_ERROR -1 68 69#define closesocket close 70 71#elif defined( TORQUE_OS_LINUX ) 72 73#include <unistd.h> 74#include <sys/types.h> 75#include <sys/socket.h> 76#include <sys/poll.h> 77#include <arpa/inet.h> 78#include <netdb.h> 79#include <netinet/in.h> 80#include <errno.h> 81#include <sys/ioctl.h> 82#include <net/if.h> 83 84typedef sockaddr_in SOCKADDR_IN; 85typedef sockaddr_in6 SOCKADDR_IN6; 86typedef sockaddr * PSOCKADDR; 87typedef sockaddr SOCKADDR; 88typedef in_addr IN_ADDR; 89typedef in6_addr IN6_ADDR; 90typedef int SOCKET; 91 92#define INVALID_SOCKET -1 93#define SOCKET_ERROR -1 94 95#define closesocket close 96 97#endif 98 99#if defined(TORQUE_USE_WINSOCK) 100static const char* strerror_wsa( S32 code ) 101{ 102 switch( code ) 103 { 104#define E( name ) case name: return #name; 105 E( WSANOTINITIALISED ); 106 E( WSAENETDOWN ); 107 E( WSAEADDRINUSE ); 108 E( WSAEINPROGRESS ); 109 E( WSAEALREADY ); 110 E( WSAEADDRNOTAVAIL ); 111 E( WSAEAFNOSUPPORT ); 112 E( WSAEFAULT ); 113 E( WSAEINVAL ); 114 E( WSAEISCONN ); 115 E( WSAENETUNREACH ); 116 E( WSAEHOSTUNREACH ); 117 E( WSAENOBUFS ); 118 E( WSAENOTSOCK ); 119 E( WSAETIMEDOUT ); 120 E( WSAEWOULDBLOCK ); 121 E( WSAEACCES ); 122#undef E 123 default: 124 return "Unknown"; 125 } 126} 127#endif 128 129#include "core/util/tVector.h" 130#include "platform/platformNetAsync.h" 131#include "console/console.h" 132#include "core/util/journal/process.h" 133#include "core/util/journal/journal.h" 134 135 136NetSocket NetSocket::INVALID = NetSocket::fromHandle(-1); 137 138template<class T> class ReservedSocketList 139{ 140public: 141 struct EntryType 142 { 143 T value; 144 bool used; 145 146 EntryType() : value(-1), used(false) { ; } 147 148 bool operator==(const EntryType &e1) 149 { 150 return value == e1.value && used == e1.used; 151 } 152 153 bool operator!=(const EntryType &e1) 154 { 155 return !(value == e1.value && used == e1.used); 156 } 157 }; 158 159 Vector<EntryType> mSocketList; 160 Mutex *mMutex; 161 162 ReservedSocketList() 163 { 164 mMutex = new Mutex; 165 } 166 167 ~ReservedSocketList() 168 { 169 delete mMutex; 170 } 171 172 inline void modify() { Mutex::lockMutex(mMutex); } 173 inline void endModify() { Mutex::unlockMutex(mMutex); } 174 175 NetSocket reserve(SOCKET reserveId = -1, bool doLock = true); 176 void remove(NetSocket socketToRemove, bool doLock = true); 177 178 T activate(NetSocket socketToActivate, int family, bool useUDP, bool clearOnFail = false); 179 T resolve(NetSocket socketToResolve); 180}; 181 182const SOCKET InvalidSocketHandle = -1; 183 184static void IPSocketToNetAddress(const struct sockaddr_in *sockAddr, NetAddress *address); 185static void IPSocket6ToNetAddress(const struct sockaddr_in6 *sockAddr, NetAddress *address); 186 187namespace PlatformNetState 188{ 189 static S32 initCount = 0; 190 191 static const S32 defaultPort = 28000; 192 static S32 netPort = 0; 193 194 static NetSocket udpSocket = NetSocket::INVALID; 195 static NetSocket udp6Socket = NetSocket::INVALID; 196 static NetSocket multicast6Socket = NetSocket::INVALID; 197 198 static ipv6_mreq multicast6Group; 199 200 static ReservedSocketList<SOCKET> smReservedSocketList; 201 202 Net::Error getLastError() 203 { 204#if defined(TORQUE_USE_WINSOCK) 205 S32 err = WSAGetLastError(); 206 switch (err) 207 { 208 case 0: 209 return Net::NoError; 210 case WSAEWOULDBLOCK: 211 return Net::WouldBlock; 212 default: 213 return Net::UnknownError; 214 } 215#else 216 int theError = errno; 217 if (errno == EAGAIN) 218 return Net::WouldBlock; 219 if (errno == 0) 220 return Net::NoError; 221 if (errno == EINPROGRESS) 222 return Net::WouldBlock; 223 224 return Net::UnknownError; 225#endif 226 } 227 228 S32 getDefaultGameProtocol() 229 { 230 // we turn off VDP in non-release builds because VDP does not support broadcast packets 231 // which are required for LAN queries (PC->Xbox connectivity). The wire protocol still 232 // uses the VDP packet structure, though. 233 S32 protocol = IPPROTO_UDP; 234#ifdef TORQUE_DISABLE_PC_CONNECTIVITY 235 // Xbox uses a VDP (voice/data protocol) socket for networking 236 protocol = IPPROTO_VDP; 237 useVDP = true; 238#endif 239 240 return protocol; 241 } 242 243 struct addrinfo* pickAddressByProtocol(struct addrinfo* addr, int protocol) 244 { 245 for (addr; addr != NULL; addr = addr->ai_next) 246 { 247 if (addr->ai_family == protocol) 248 return addr; 249 } 250 251 return NULL; 252 } 253 254 /// Extracts core address parts from an address string. Returns false if it's malformed. 255 bool extractAddressParts(const char *addressString, char outAddress[256], int &outPort, int &outFamily) 256 { 257 outPort = 0; 258 outFamily = AF_UNSPEC; 259 260 if (!dStrnicmp(addressString, "ipx:", 4)) 261 // ipx support deprecated 262 return false; 263 264 if (!dStrnicmp(addressString, "ip:", 3)) 265 { 266 addressString += 3; // eat off the ip: 267 outFamily = AF_INET; 268 } 269 else if (!dStrnicmp(addressString, "ip6:", 4)) 270 { 271 addressString += 4; // eat off the ip6: 272 outFamily = AF_INET6; 273 } 274 275 if (strlen(addressString) > 255) 276 return false; 277 278 char *portString = NULL; 279 280 if (addressString[0] == '[') 281 { 282 // Must be ipv6 notation 283 dStrcpy(outAddress, addressString+1, 256); 284 addressString = outAddress; 285 286 portString = dStrchr(outAddress, ']'); 287 if (portString) 288 { 289 // Sort out the :port after the ] 290 *portString++ = '\0'; 291 if (*portString != ':') 292 { 293 portString = NULL; 294 } 295 else 296 { 297 *portString++ = '\0'; 298 } 299 } 300 301 if (outFamily == AF_UNSPEC) 302 { 303 outFamily = AF_INET6; 304 } 305 } 306 else 307 { 308 dStrcpy(outAddress, addressString, 256); 309 addressString = outAddress; 310 311 // Check to see if we have multiple ":" which would indicate this is an ipv6 address 312 char* scan = outAddress; 313 int colonCount = 0; 314 while (*scan != '\0' && colonCount < 2) 315 { 316 if (*scan++ == ':') 317 colonCount++; 318 } 319 if (colonCount <= 1) 320 { 321 // either ipv4 or host 322 portString = dStrchr(outAddress, ':'); 323 324 if (portString) 325 { 326 *portString++ = '\0'; 327 } 328 } 329 else if (outFamily == AF_UNSPEC) 330 { 331 // Must be ipv6 332 outFamily = AF_INET6; 333 } 334 } 335 336 if (portString) 337 { 338 outPort = dAtoi(portString); 339 } 340 341 return true; 342 } 343 344 Net::Error getSocketAddress(SOCKET socketFd, int requiredFamily, NetAddress *outAddress) 345 { 346 Net::Error error = Net::UnknownError; 347 348 if (requiredFamily == AF_INET) 349 { 350 sockaddr_in ipAddr; 351 socklen_t len = sizeof(ipAddr); 352 if (getsockname(socketFd, (struct sockaddr*)&ipAddr, &len) >= 0) 353 { 354 IPSocketToNetAddress(&ipAddr, outAddress); 355 error = Net::NoError; 356 } 357 else 358 { 359 error = getLastError(); 360 } 361 } 362 else if (requiredFamily == AF_INET6) 363 { 364 sockaddr_in6 ipAddr; 365 socklen_t len = sizeof(ipAddr); 366 if (getsockname(socketFd, (struct sockaddr*)&ipAddr, &len) >= 0) 367 { 368 IPSocket6ToNetAddress(&ipAddr, outAddress); 369 error = Net::NoError; 370 } 371 else 372 { 373 error = getLastError(); 374 } 375 } 376 377 return error; 378 } 379}; 380 381 382 383template<class T> NetSocket ReservedSocketList<T>::reserve(SOCKET reserveId, bool doLock) 384{ 385 MutexHandle handle; 386 if (doLock) 387 { 388 handle.lock(mMutex, true); 389 } 390 391 S32 idx = mSocketList.find_next(EntryType()); 392 if (idx == -1) 393 { 394 EntryType entry; 395 entry.value = reserveId; 396 entry.used = true; 397 mSocketList.push_back(entry); 398 return NetSocket::fromHandle(mSocketList.size() - 1); 399 } 400 else 401 { 402 EntryType &entry = mSocketList[idx]; 403 entry.used = true; 404 entry.value = reserveId; 405 } 406 407 return NetSocket::fromHandle(idx); 408} 409 410template<class T> void ReservedSocketList<T>::remove(NetSocket socketToRemove, bool doLock) 411{ 412 MutexHandle handle; 413 if (doLock) 414 { 415 handle.lock(mMutex, true); 416 } 417 418 if ((U32)socketToRemove.getHandle() >= (U32)mSocketList.size()) 419 return; 420 421 mSocketList[socketToRemove.getHandle()] = EntryType(); 422} 423 424template<class T> T ReservedSocketList<T>::activate(NetSocket socketToActivate, int family, bool useUDP, bool clearOnFail) 425{ 426 MutexHandle h; 427 h.lock(mMutex, true); 428 429 int typeID = useUDP ? SOCK_DGRAM : SOCK_STREAM; 430 int protocol = useUDP ? PlatformNetState::getDefaultGameProtocol() : 0; 431 432 if ((U32)socketToActivate.getHandle() >= (U32)mSocketList.size()) 433 return -1; 434 435 EntryType &entry = mSocketList[socketToActivate.getHandle()]; 436 if (!entry.used) 437 return -1; 438 439 T socketFd = entry.value; 440 if (socketFd == -1) 441 { 442 socketFd = ::socket(family, typeID, protocol); 443 444 if (socketFd == InvalidSocketHandle) 445 { 446 if (clearOnFail) 447 { 448 remove(socketToActivate, false); 449 } 450 return InvalidSocketHandle; 451 } 452 else 453 { 454 entry.used = true; 455 entry.value = socketFd; 456 return socketFd; 457 } 458 } 459 460 return socketFd; 461} 462 463template<class T> T ReservedSocketList<T>::resolve(NetSocket socketToResolve) 464{ 465 MutexHandle h; 466 h.lock(mMutex, true); 467 468 if ((U32)socketToResolve.getHandle() >= (U32)mSocketList.size()) 469 return -1; 470 471 EntryType &entry = mSocketList[socketToResolve.getHandle()]; 472 return entry.used ? entry.value : -1; 473} 474 475ConnectionNotifyEvent* Net::smConnectionNotify = NULL; 476ConnectionAcceptedEvent* Net::smConnectionAccept = NULL; 477ConnectionReceiveEvent* Net::smConnectionReceive = NULL; 478PacketReceiveEvent* Net::smPacketReceive = NULL; 479 480ConnectionNotifyEvent& Net::getConnectionNotifyEvent() 481{ 482 return *smConnectionNotify; 483} 484 485ConnectionAcceptedEvent& Net::getConnectionAcceptedEvent() 486{ 487 return *smConnectionAccept; 488} 489 490ConnectionReceiveEvent& Net::getConnectionReceiveEvent() 491{ 492 return *smConnectionReceive; 493} 494 495PacketReceiveEvent& Net::getPacketReceiveEvent() 496{ 497 return *smPacketReceive; 498} 499 500// Multicast stuff 501bool Net::smMulticastEnabled = true; 502// 503// Protocol Stuff 504bool Net::smIpv4Enabled = true; 505bool Net::smIpv6Enabled = false; 506// 507 508// the Socket structure helps us keep track of the 509// above states 510struct PolledSocket 511{ 512 // local enum for socket states for polled sockets 513 enum SocketState 514 { 515 InvalidState, 516 Connected, 517 ConnectionPending, 518 Listening, 519 NameLookupRequired 520 }; 521 522 PolledSocket() 523 { 524 fd = -1; 525 handleFd = NetSocket::INVALID; 526 state = InvalidState; 527 remoteAddr[0] = 0; 528 remotePort = -1; 529 } 530 531 SOCKET fd; 532 NetSocket handleFd; 533 S32 state; 534 char remoteAddr[256]; 535 S32 remotePort; 536}; 537 538// list of polled sockets 539static Vector<PolledSocket*> gPolledSockets( __FILE__, __LINE__ ); 540 541static PolledSocket* addPolledSocket(NetSocket handleFd, SOCKET fd, S32 state, 542 char* remoteAddr = NULL, S32 port = -1) 543{ 544 PolledSocket* sock = new PolledSocket(); 545 sock->fd = fd; 546 sock->handleFd = handleFd; 547 sock->state = state; 548 if (remoteAddr) 549 dStrcpy(sock->remoteAddr, remoteAddr, 256); 550 if (port != -1) 551 sock->remotePort = port; 552 gPolledSockets.push_back(sock); 553 return sock; 554} 555 556bool netSocketWaitForWritable(NetSocket handleFd, S32 timeoutMs) 557{ 558 fd_set writefds; 559 timeval timeout; 560 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 561 562 FD_ZERO( &writefds ); 563 FD_SET( socketFd, &writefds ); 564 565 timeout.tv_sec = timeoutMs / 1000; 566 timeout.tv_usec = ( timeoutMs % 1000 ) * 1000; 567 568 if( select(socketFd + 1, NULL, &writefds, NULL, &timeout) > 0 ) 569 return true; 570 571 return false; 572} 573 574bool Net::init() 575{ 576#if defined(TORQUE_USE_WINSOCK) 577 if(!PlatformNetState::initCount) 578 { 579 WSADATA stWSAData; 580 AssertISV( !WSAStartup( 0x0101, &stWSAData ), "Net::init - failed to init WinSock!" ); 581 582 //logprintf("Winsock initialization %s", success ? "succeeded." : "failed!"); 583 } 584#endif 585 PlatformNetState::initCount++; 586 587 smConnectionNotify = new ConnectionNotifyEvent(); 588 smConnectionAccept = new ConnectionAcceptedEvent(); 589 smConnectionReceive = new ConnectionReceiveEvent(); 590 smPacketReceive = new PacketReceiveEvent(); 591 592 593 Process::notify(&Net::process, PROCESS_NET_ORDER); 594 595 return(true); 596} 597 598void Net::shutdown() 599{ 600 Process::remove(&Net::process); 601 602 while (gPolledSockets.size() > 0) 603 { 604 if (gPolledSockets[0] == NULL) 605 gPolledSockets.erase(gPolledSockets.begin()); 606 else 607 closeConnectTo(gPolledSockets[0]->handleFd); 608 } 609 610 closePort(); 611 PlatformNetState::initCount--; 612 613 // Destroy event handlers 614 delete smConnectionNotify; 615 delete smConnectionAccept; 616 delete smConnectionReceive; 617 delete smPacketReceive; 618 619#if defined(TORQUE_USE_WINSOCK) 620 if(!PlatformNetState::initCount) 621 { 622 WSACleanup(); 623 } 624#endif 625} 626 627// ipv4 version of name routines 628 629static void NetAddressToIPSocket(const NetAddress *address, struct sockaddr_in *sockAddr) 630{ 631 dMemset(sockAddr, 0, sizeof(struct sockaddr_in)); 632 sockAddr->sin_family = AF_INET; 633 sockAddr->sin_port = htons(address->port); 634 #if defined(TORQUE_OS_BSD) || defined(TORQUE_OS_MAC) 635 sockAddr->sin_len = sizeof(struct sockaddr_in); 636 #endif 637 if (address->type == NetAddress::IPBroadcastAddress) 638 { 639 sockAddr->sin_addr.s_addr = htonl(INADDR_BROADCAST); 640 } 641 else 642 { 643 dMemcpy(&sockAddr->sin_addr, &address->address.ipv4.netNum[0], 4); 644 } 645} 646 647static void IPSocketToNetAddress(const struct sockaddr_in *sockAddr, NetAddress *address) 648{ 649 address->type = NetAddress::IPAddress; 650 address->port = ntohs(sockAddr->sin_port); 651 dMemcpy(&address->address.ipv4.netNum[0], &sockAddr->sin_addr, 4); 652} 653 654// ipv6 version of name routines 655 656static void NetAddressToIPSocket6(const NetAddress *address, struct sockaddr_in6 *sockAddr) 657{ 658 dMemset(sockAddr, 0, sizeof(struct sockaddr_in6)); 659#ifdef SIN6_LEN 660 sockAddr->sin6_len = sizeof(struct sockaddr_in6); 661#endif 662 sockAddr->sin6_family = AF_INET6; 663 sockAddr->sin6_port = ntohs(address->port); 664 665 if (address->type == NetAddress::IPV6MulticastAddress) 666 { 667 sockAddr->sin6_addr = PlatformNetState::multicast6Group.ipv6mr_multiaddr; 668 sockAddr->sin6_scope_id = PlatformNetState::multicast6Group.ipv6mr_interface; 669 } 670 else 671 { 672 sockAddr->sin6_flowinfo = address->address.ipv6.netFlow; 673 sockAddr->sin6_scope_id = address->address.ipv6.netScope; 674 dMemcpy(&sockAddr->sin6_addr, address->address.ipv6.netNum, sizeof(address->address.ipv6.netNum)); 675 } 676} 677 678static void IPSocket6ToNetAddress(const struct sockaddr_in6 *sockAddr, NetAddress *address) 679{ 680 address->type = NetAddress::IPV6Address; 681 address->port = ntohs(sockAddr->sin6_port); 682 dMemcpy(address->address.ipv6.netNum, &sockAddr->sin6_addr, sizeof(address->address.ipv6.netNum)); 683 address->address.ipv6.netFlow = sockAddr->sin6_flowinfo; 684 address->address.ipv6.netScope = sockAddr->sin6_scope_id; 685} 686 687// 688 689NetSocket Net::openListenPort(U16 port, NetAddress::Type addressType) 690{ 691 if(Journal::IsPlaying()) 692 { 693 U32 ret; 694 Journal::Read(&ret); 695 return NetSocket::fromHandle(ret); 696 } 697 698 Net::Error error = NoError; 699 NetAddress address; 700 if (Net::getListenAddress(addressType, &address) != Net::NoError) 701 error = Net::WrongProtocolType; 702 703 NetSocket handleFd = NetSocket::INVALID; 704 SOCKET sockId = InvalidSocketHandle; 705 706 if (error == NoError) 707 { 708 handleFd = openSocket(); 709 sockId = PlatformNetState::smReservedSocketList.activate(handleFd, address.type == NetAddress::IPAddress ? AF_INET : AF_INET6, false, true); 710 } 711 712 if (error == NoError && (handleFd == NetSocket::INVALID || sockId == InvalidSocketHandle)) 713 { 714 Con::errorf("Unable to open listen socket: %s", strerror(errno)); 715 error = NotASocket; 716 handleFd = NetSocket::INVALID; 717 } 718 719 if (error == NoError) 720 { 721 address.port = port; 722 error = bindAddress(address, handleFd, false); 723 if (error != NoError) 724 { 725 Con::errorf("Unable to bind port %d: %s", port, strerror(errno)); 726 closeSocket(handleFd); 727 handleFd = NetSocket::INVALID; 728 } 729 } 730 731 if (error == NoError) 732 { 733 error = listen(handleFd, 4); 734 if (error != NoError) 735 { 736 Con::errorf("Unable to listen on port %d: %s", port, strerror(errno)); 737 closeSocket(handleFd); 738 handleFd = NetSocket::INVALID; 739 } 740 } 741 742 if (error == NoError) 743 { 744 setBlocking(handleFd, false); 745 addPolledSocket(handleFd, sockId, PolledSocket::Listening); 746 } 747 748 if(Journal::IsRecording()) 749 Journal::Write(U32(handleFd.getHandle())); 750 751 return handleFd; 752} 753 754NetSocket Net::openConnectTo(const char *addressString) 755{ 756 if (Journal::IsPlaying()) 757 { 758 U32 ret; 759 Journal::Read(&ret); 760 return NetSocket::fromHandle(ret); 761 } 762 763 NetAddress address; 764 NetSocket handleFd = NetSocket::INVALID; 765 Net::Error error = NoError; 766 767 error = Net::stringToAddress(addressString, &address, false); 768 769 if (error == NoError && address.type != NetAddress::IPAddress && address.type != NetAddress::IPV6Address) 770 { 771 error = Net::WrongProtocolType; 772 } 773 774 // Open socket 775 if (error == NoError || error == NeedHostLookup) 776 { 777 handleFd = openSocket(); 778 } 779 780 // Attempt to connect or queue a lookup 781 if (error == NoError && address.type == NetAddress::IPAddress) 782 { 783 sockaddr_in ipAddr; 784 NetAddressToIPSocket(&address, &ipAddr); 785 SOCKET socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET, false, true); 786 if (socketFd != InvalidSocketHandle) 787 { 788 setBlocking(handleFd, false); 789 if (::connect(socketFd, (struct sockaddr *)&ipAddr, sizeof(ipAddr)) == -1) 790 { 791 Net::Error err = PlatformNetState::getLastError(); 792 if (err != Net::WouldBlock) 793 { 794 Con::errorf("Error connecting to %s: %u", 795 addressString, err); 796 closeSocket(handleFd); 797 handleFd = NetSocket::INVALID; 798 } 799 } 800 } 801 else 802 { 803 PlatformNetState::smReservedSocketList.remove(handleFd); 804 handleFd = NetSocket::INVALID; 805 } 806 807 if (handleFd != NetSocket::INVALID) 808 { 809 // add this socket to our list of polled sockets 810 addPolledSocket(handleFd, socketFd, PolledSocket::ConnectionPending); 811 } 812 } 813 else if (error == NoError && address.type == NetAddress::IPV6Address) 814 { 815 sockaddr_in6 ipAddr6; 816 NetAddressToIPSocket6(&address, &ipAddr6); 817 SOCKET socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET6, false, true); 818 if (socketFd != InvalidSocketHandle) 819 { 820 setBlocking(handleFd, false); 821 if (::connect(socketFd, (struct sockaddr *)&ipAddr6, sizeof(ipAddr6)) == -1) 822 { 823 Net::Error err = PlatformNetState::getLastError(); 824 if (err != Net::WouldBlock) 825 { 826 Con::errorf("Error connecting to %s: %u", 827 addressString, err); 828 closeSocket(handleFd); 829 handleFd = NetSocket::INVALID; 830 } 831 } 832 } 833 else 834 { 835 PlatformNetState::smReservedSocketList.remove(handleFd); 836 handleFd = NetSocket::INVALID; 837 } 838 839 if (handleFd != NetSocket::INVALID) 840 { 841 // add this socket to our list of polled sockets 842 addPolledSocket(handleFd, socketFd, PolledSocket::ConnectionPending); 843 } 844 } 845 else if (error == Net::NeedHostLookup) 846 { 847 // need to do an asynchronous name lookup. first, add the socket 848 // to the polled list 849 char addr[256]; 850 int port = 0; 851 int actualFamily = AF_UNSPEC; 852 if (PlatformNetState::extractAddressParts(addressString, addr, port, actualFamily)) 853 { 854 addPolledSocket(handleFd, InvalidSocketHandle, PolledSocket::NameLookupRequired, addr, port); 855 // queue the lookup 856 gNetAsync.queueLookup(addressString, handleFd); 857 } 858 else 859 { 860 closeSocket(handleFd); 861 handleFd = NetSocket::INVALID; 862 } 863 } 864 else 865 { 866 closeSocket(handleFd); 867 handleFd = NetSocket::INVALID; 868 } 869 870 if (Journal::IsRecording()) 871 Journal::Write(U32(handleFd.getHandle())); 872 return handleFd; 873} 874 875void Net::closeConnectTo(NetSocket handleFd) 876{ 877 if(Journal::IsPlaying()) 878 return; 879 880 // if this socket is in the list of polled sockets, remove it 881 for (S32 i = 0; i < gPolledSockets.size(); ++i) 882 { 883 if (gPolledSockets[i] && gPolledSockets[i]->handleFd == handleFd) 884 { 885 delete gPolledSockets[i]; 886 gPolledSockets[i] = NULL; 887 break; 888 } 889 } 890 891 closeSocket(handleFd); 892} 893 894Net::Error Net::sendtoSocket(NetSocket handleFd, const U8 *buffer, S32 bufferSize, S32 *outBufferWritten) 895{ 896 if(Journal::IsPlaying()) 897 { 898 U32 e; 899 S32 outBytes; 900 Journal::Read(&e); 901 Journal::Read(&outBytes); 902 if (outBufferWritten) 903 *outBufferWritten = outBytes; 904 905 return (Net::Error) e; 906 } 907 908 S32 outBytes = 0; 909 Net::Error e = send(handleFd, buffer, bufferSize, &outBytes); 910 911 if (Journal::IsRecording()) 912 { 913 Journal::Write(U32(e)); 914 Journal::Write(outBytes); 915 } 916 917 if (outBufferWritten) 918 *outBufferWritten = outBytes; 919 920 return e; 921} 922 923bool Net::openPort(S32 port, bool doBind) 924{ 925 if (PlatformNetState::udpSocket != NetSocket::INVALID) 926 { 927 closeSocket(PlatformNetState::udpSocket); 928 PlatformNetState::udpSocket = NetSocket::INVALID; 929 } 930 if (PlatformNetState::udp6Socket != NetSocket::INVALID) 931 { 932 closeSocket(PlatformNetState::udp6Socket); 933 PlatformNetState::udp6Socket = NetSocket::INVALID; 934 } 935 936 // Update prefs 937 Net::smMulticastEnabled = Con::getBoolVariable("pref::Net::Multicast6Enabled", true); 938 Net::smIpv4Enabled = Con::getBoolVariable("pref::Net::IPV4Enabled", true); 939 Net::smIpv6Enabled = Con::getBoolVariable("pref::Net::IPV6Enabled", false); 940 941 // we turn off VDP in non-release builds because VDP does not support broadcast packets 942 // which are required for LAN queries (PC->Xbox connectivity). The wire protocol still 943 // uses the VDP packet structure, though. 944 S32 protocol = PlatformNetState::getDefaultGameProtocol(); 945 946 SOCKET socketFd = InvalidSocketHandle; 947 NetAddress address; 948 NetAddress listenAddress; 949 char listenAddressStr[256]; 950 951 if (Net::smIpv4Enabled) 952 { 953 if (Net::getListenAddress(NetAddress::IPAddress, &address) == Net::NoError) 954 { 955 address.port = port; 956 socketFd = ::socket(AF_INET, SOCK_DGRAM, protocol); 957 958 if (socketFd != InvalidSocketHandle) 959 { 960 PlatformNetState::udpSocket = PlatformNetState::smReservedSocketList.reserve(socketFd); 961 Net::Error error = NoError; 962 if (doBind) 963 { 964 error = bindAddress(address, PlatformNetState::udpSocket, true); 965 } 966 967 if (error == NoError) 968 error = setBufferSize(PlatformNetState::udpSocket, 32768 * 8); 969 970#ifndef TORQUE_DISABLE_PC_CONNECTIVITY 971 if (error == NoError) 972 error = setBroadcast(PlatformNetState::udpSocket, true); 973#endif 974 975 if (error == NoError) 976 error = setBlocking(PlatformNetState::udpSocket, false); 977 978 if (error == NoError) 979 { 980 error = PlatformNetState::getSocketAddress(socketFd, AF_INET, &listenAddress); 981 if (error == NoError) 982 { 983 Net::addressToString(&listenAddress, listenAddressStr); 984 Con::printf("UDP initialized on ipv4 %s", listenAddressStr); 985 } 986 } 987 988 if (error != NoError) 989 { 990 closeSocket(PlatformNetState::udpSocket); 991 PlatformNetState::udpSocket = NetSocket::INVALID; 992 Con::printf("Unable to initialize UDP on ipv4 - error %d", error); 993 } 994 } 995 } 996 else 997 { 998 Con::errorf("Unable to initialize UDP on ipv4 - invalid address."); 999 PlatformNetState::udpSocket = NetSocket::INVALID; 1000 } 1001 } 1002 1003 if (Net::smIpv6Enabled) 1004 { 1005 if (Net::getListenAddress(NetAddress::IPV6Address, &address) == Net::NoError) 1006 { 1007 address.port = port; 1008 socketFd = ::socket(AF_INET6, SOCK_DGRAM, protocol); 1009 1010 if (socketFd != InvalidSocketHandle) 1011 { 1012 PlatformNetState::udp6Socket = PlatformNetState::smReservedSocketList.reserve(socketFd); 1013 1014 Net::Error error = NoError; 1015 1016 int v = 1; 1017 setsockopt(socketFd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&v, sizeof(v)); 1018 PlatformNetState::getLastError(); 1019 1020 if (doBind) 1021 { 1022 error = bindAddress(address, PlatformNetState::udp6Socket, true); 1023 } 1024 1025 if (error == NoError) 1026 error = setBufferSize(PlatformNetState::udp6Socket, 32768 * 8); 1027 1028 if (error == NoError) 1029 error = setBlocking(PlatformNetState::udp6Socket, false); 1030 1031 if (error == NoError) 1032 { 1033 error = PlatformNetState::getSocketAddress(socketFd, AF_INET6, &listenAddress); 1034 if (error == NoError) 1035 { 1036 Net::addressToString(&listenAddress, listenAddressStr); 1037 Con::printf("UDP initialized on ipv6 %s", listenAddressStr); 1038 } 1039 } 1040 1041 if (error != NoError) 1042 { 1043 closeSocket(PlatformNetState::udp6Socket); 1044 PlatformNetState::udp6Socket = NetSocket::INVALID; 1045 Con::printf("Unable to initialize UDP on ipv6 - error %d", error); 1046 } 1047 1048 if (Net::smMulticastEnabled && doBind) 1049 { 1050 Net::enableMulticast(); 1051 } 1052 else 1053 { 1054 Net::disableMulticast(); 1055 } 1056 } 1057 } 1058 } 1059 1060 PlatformNetState::netPort = port; 1061 1062 return PlatformNetState::udpSocket != NetSocket::INVALID || PlatformNetState::udp6Socket != NetSocket::INVALID; 1063} 1064 1065NetSocket Net::getPort() 1066{ 1067 return PlatformNetState::udpSocket; 1068} 1069 1070void Net::closePort() 1071{ 1072 if (PlatformNetState::udpSocket != NetSocket::INVALID) 1073 closeSocket(PlatformNetState::udpSocket); 1074 if (PlatformNetState::udp6Socket != NetSocket::INVALID) 1075 closeSocket(PlatformNetState::udp6Socket); 1076} 1077 1078Net::Error Net::sendto(const NetAddress *address, const U8 *buffer, S32 bufferSize) 1079{ 1080 if(Journal::IsPlaying()) 1081 return NoError; 1082 1083 SOCKET socketFd; 1084 1085 if(address->type == NetAddress::IPAddress || address->type == NetAddress::IPBroadcastAddress) 1086 { 1087 socketFd = PlatformNetState::smReservedSocketList.resolve(PlatformNetState::udpSocket); 1088 if (socketFd != InvalidSocketHandle) 1089 { 1090 sockaddr_in ipAddr; 1091 NetAddressToIPSocket(address, &ipAddr); 1092 1093 if (::sendto(socketFd, (const char*)buffer, bufferSize, 0, 1094 (sockaddr *)&ipAddr, sizeof(sockaddr_in)) == SOCKET_ERROR) 1095 return PlatformNetState::getLastError(); 1096 else 1097 return NoError; 1098 } 1099 else 1100 { 1101 return NotASocket; 1102 } 1103 } 1104 else if (address->type == NetAddress::IPV6Address || address->type == NetAddress::IPV6MulticastAddress) 1105 { 1106 socketFd = PlatformNetState::smReservedSocketList.resolve(address->type == NetAddress::IPV6MulticastAddress ? PlatformNetState::multicast6Socket : PlatformNetState::udp6Socket); 1107 1108 if (socketFd != InvalidSocketHandle) 1109 { 1110 sockaddr_in6 ipAddr; 1111 NetAddressToIPSocket6(address, &ipAddr); 1112 if (::sendto(socketFd, (const char*)buffer, bufferSize, 0, 1113 (struct sockaddr *) &ipAddr, sizeof(sockaddr_in6)) == SOCKET_ERROR) 1114 return PlatformNetState::getLastError(); 1115 else 1116 return NoError; 1117 } 1118 else 1119 { 1120 return NotASocket; 1121 } 1122 } 1123 1124 return WrongProtocolType; 1125} 1126 1127void Net::process() 1128{ 1129 // Process listening sockets 1130 processListenSocket(PlatformNetState::udpSocket); 1131 processListenSocket(PlatformNetState::udp6Socket); 1132 1133 // process the polled sockets. This blob of code performs functions 1134 // similar to WinsockProc in winNet.cc 1135 1136 if (gPolledSockets.size() == 0) 1137 return; 1138 1139 S32 optval; 1140 socklen_t optlen = sizeof(S32); 1141 S32 bytesRead; 1142 Net::Error err; 1143 bool removeSock = false; 1144 PolledSocket *currentSock = NULL; 1145 NetSocket incomingHandleFd = NetSocket::INVALID; 1146 NetAddress out_h_addr; 1147 S32 out_h_length = 0; 1148 RawData readBuff; 1149 NetSocket removeSockHandle; 1150 1151 for (S32 i = 0; i < gPolledSockets.size(); 1152 /* no increment, this is done at end of loop body */) 1153 { 1154 removeSock = false; 1155 currentSock = gPolledSockets[i]; 1156 1157 // Cleanup if we've removed it 1158 if (currentSock == NULL) 1159 { 1160 gPolledSockets.erase(i); 1161 continue; 1162 } 1163 1164 switch (currentSock->state) 1165 { 1166 case PolledSocket::InvalidState: 1167 Con::errorf("Error, InvalidState socket in polled sockets list"); 1168 break; 1169 case PolledSocket::ConnectionPending: 1170 // see if it is now connected 1171 if (getsockopt(currentSock->fd, SOL_SOCKET, SO_ERROR, 1172 (char*)&optval, &optlen) == -1) 1173 { 1174 Con::errorf("Error getting socket options: %s", strerror(errno)); 1175 1176 removeSock = true; 1177 removeSockHandle = currentSock->handleFd; 1178 1179 smConnectionNotify->trigger(currentSock->handleFd, Net::ConnectFailed); 1180 } 1181 else 1182 { 1183 if (optval == EINPROGRESS) 1184 // still connecting... 1185 break; 1186 1187 if (optval == 0) 1188 { 1189 // poll for writable status to be sure we're connected. 1190 bool ready = netSocketWaitForWritable(currentSock->handleFd,0); 1191 if(!ready) 1192 break; 1193 1194 currentSock->state = PolledSocket::Connected; 1195 smConnectionNotify->trigger(currentSock->handleFd, Net::Connected); 1196 } 1197 else 1198 { 1199 // some kind of error 1200 Con::errorf("Error connecting: %s", strerror(errno)); 1201 1202 removeSock = true; 1203 removeSockHandle = currentSock->handleFd; 1204 1205 smConnectionNotify->trigger(currentSock->handleFd, Net::ConnectFailed); 1206 } 1207 } 1208 break; 1209 case PolledSocket::Connected: 1210 1211 // try to get some data 1212 bytesRead = 0; 1213 readBuff.alloc(MaxPacketDataSize); 1214 err = Net::recv(currentSock->handleFd, (U8*)readBuff.data, MaxPacketDataSize, &bytesRead); 1215 if(err == Net::NoError) 1216 { 1217 if (bytesRead > 0) 1218 { 1219 // got some data, post it 1220 readBuff.size = bytesRead; 1221 smConnectionReceive->trigger(currentSock->handleFd, readBuff); 1222 } 1223 else 1224 { 1225 // ack! this shouldn't happen 1226 if (bytesRead < 0) 1227 Con::errorf("Unexpected error on socket: %s", strerror(errno)); 1228 1229 removeSock = true; 1230 removeSockHandle = currentSock->handleFd; 1231 1232 // zero bytes read means EOF 1233 smConnectionNotify->trigger(currentSock->handleFd, Net::Disconnected); 1234 } 1235 } 1236 else if (err != Net::NoError && err != Net::WouldBlock) 1237 { 1238 Con::errorf("Error reading from socket: %s", strerror(errno)); 1239 1240 removeSock = true; 1241 removeSockHandle = currentSock->handleFd; 1242 1243 smConnectionNotify->trigger(currentSock->handleFd, Net::Disconnected); 1244 } 1245 break; 1246 case PolledSocket::NameLookupRequired: 1247 U32 newState; 1248 1249 // is the lookup complete? 1250 if (!gNetAsync.checkLookup( 1251 currentSock->handleFd, &out_h_addr, &out_h_length, 1252 sizeof(out_h_addr))) 1253 break; 1254 1255 if (out_h_length == -1) 1256 { 1257 Con::errorf("DNS lookup failed: %s", currentSock->remoteAddr); 1258 newState = Net::DNSFailed; 1259 removeSock = true; 1260 removeSockHandle = currentSock->handleFd; 1261 } 1262 else 1263 { 1264 // try to connect 1265 out_h_addr.port = currentSock->remotePort; 1266 const sockaddr *ai_addr = NULL; 1267 int ai_addrlen = 0; 1268 sockaddr_in socketAddress; 1269 sockaddr_in6 socketAddress6; 1270 1271 if (out_h_addr.type == NetAddress::IPAddress) 1272 { 1273 ai_addr = (const sockaddr*)&socketAddress; 1274 ai_addrlen = sizeof(socketAddress); 1275 NetAddressToIPSocket(&out_h_addr, &socketAddress); 1276 1277 currentSock->fd = PlatformNetState::smReservedSocketList.activate(currentSock->handleFd, AF_INET, false); 1278 setBlocking(currentSock->handleFd, false); 1279 1280#ifdef TORQUE_DEBUG_LOOKUPS 1281 char addrString[256]; 1282 NetAddress addr; 1283 IPSocketToNetAddress(&socketAddress, &addr); 1284 Net::addressToString(&addr, addrString); 1285 Con::printf("DNS: lookup resolved to %s", addrString); 1286#endif 1287 } 1288 else if (out_h_addr.type == NetAddress::IPV6Address) 1289 { 1290 ai_addr = (const sockaddr*)&socketAddress6; 1291 ai_addrlen = sizeof(socketAddress6); 1292 NetAddressToIPSocket6(&out_h_addr, &socketAddress6); 1293 1294 currentSock->fd = PlatformNetState::smReservedSocketList.activate(currentSock->handleFd, AF_INET6, false); 1295 setBlocking(currentSock->handleFd, false); 1296 1297#ifdef TORQUE_DEBUG_LOOKUPS 1298 char addrString[256]; 1299 NetAddress addr; 1300 IPSocket6ToNetAddress(&socketAddress6, &addr); 1301 Net::addressToString(&addr, addrString); 1302 Con::printf("DNS: lookup resolved to %s", addrString); 1303#endif 1304 } 1305 else 1306 { 1307 Con::errorf("Error connecting to %s: Invalid Protocol", 1308 currentSock->remoteAddr); 1309 newState = Net::ConnectFailed; 1310 removeSock = true; 1311 removeSockHandle = currentSock->handleFd; 1312 } 1313 1314 if (ai_addr) 1315 { 1316 if (::connect(currentSock->fd, ai_addr, 1317 ai_addrlen) == -1) 1318 { 1319 err = PlatformNetState::getLastError(); 1320 if (err != Net::WouldBlock) 1321 { 1322 Con::errorf("Error connecting to %s: %u", 1323 currentSock->remoteAddr, err); 1324 newState = Net::ConnectFailed; 1325 removeSock = true; 1326 removeSockHandle = currentSock->handleFd; 1327 } 1328 else 1329 { 1330 newState = Net::DNSResolved; 1331 currentSock->state = PolledSocket::ConnectionPending; 1332 } 1333 } 1334 else 1335 { 1336 newState = Net::Connected; 1337 currentSock->state = Connected; 1338 } 1339 } 1340 } 1341 1342 smConnectionNotify->trigger(currentSock->handleFd, newState); 1343 break; 1344 case PolledSocket::Listening: 1345 NetAddress incomingAddy; 1346 1347 incomingHandleFd = Net::accept(currentSock->handleFd, &incomingAddy); 1348 if(incomingHandleFd != NetSocket::INVALID) 1349 { 1350 setBlocking(incomingHandleFd, false); 1351 addPolledSocket(incomingHandleFd, PlatformNetState::smReservedSocketList.resolve(incomingHandleFd), Connected); 1352 smConnectionAccept->trigger(currentSock->handleFd, incomingHandleFd, incomingAddy); 1353 } 1354 break; 1355 } 1356 1357 // only increment index if we're not removing the connection, since 1358 // the removal will shift the indices down by one 1359 if (removeSock) 1360 closeConnectTo(removeSockHandle); 1361 else 1362 i++; 1363 } 1364} 1365 1366void Net::processListenSocket(NetSocket socketHandle) 1367{ 1368 if (socketHandle == NetSocket::INVALID) 1369 return; 1370 1371 sockaddr_storage sa; 1372 sa.ss_family = AF_UNSPEC; 1373 NetAddress srcAddress; 1374 RawData tmpBuffer; 1375 tmpBuffer.alloc(Net::MaxPacketDataSize); 1376 1377 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(socketHandle); 1378 1379 for (;;) 1380 { 1381 socklen_t addrLen = sizeof(sa); 1382 S32 bytesRead = -1; 1383 1384 if (socketHandle != NetSocket::INVALID) 1385 bytesRead = ::recvfrom(socketFd, (char *)tmpBuffer.data, Net::MaxPacketDataSize, 0, (struct sockaddr*)&sa, &addrLen); 1386 1387 if (bytesRead == -1) 1388 break; 1389 1390 if (sa.ss_family == AF_INET) 1391 IPSocketToNetAddress((sockaddr_in *)&sa, &srcAddress); 1392 else if (sa.ss_family == AF_INET6) 1393 IPSocket6ToNetAddress((sockaddr_in6 *)&sa, &srcAddress); 1394 else 1395 continue; 1396 1397 if (bytesRead <= 0) 1398 continue; 1399 1400 if (srcAddress.type == NetAddress::IPAddress && 1401 srcAddress.address.ipv4.netNum[0] == 127 && 1402 srcAddress.address.ipv4.netNum[1] == 0 && 1403 srcAddress.address.ipv4.netNum[2] == 0 && 1404 srcAddress.address.ipv4.netNum[3] == 1 && 1405 srcAddress.port == PlatformNetState::netPort) 1406 continue; 1407 1408 tmpBuffer.size = bytesRead; 1409 1410 smPacketReceive->trigger(srcAddress, tmpBuffer); 1411 } 1412} 1413 1414NetSocket Net::openSocket() 1415{ 1416 return PlatformNetState::smReservedSocketList.reserve(); 1417} 1418 1419Net::Error Net::closeSocket(NetSocket handleFd) 1420{ 1421 if(handleFd != NetSocket::INVALID) 1422 { 1423 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1424 PlatformNetState::smReservedSocketList.remove(handleFd); 1425 1426 if(!::closesocket(socketFd)) 1427 return NoError; 1428 else 1429 return PlatformNetState::getLastError(); 1430 } 1431 else 1432 return NotASocket; 1433} 1434 1435Net::Error Net::connect(NetSocket handleFd, const NetAddress *address) 1436{ 1437 if(!(address->type == NetAddress::IPAddress || address->type == NetAddress::IPV6Address)) 1438 return WrongProtocolType; 1439 1440 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1441 1442 if (address->type == NetAddress::IPAddress) 1443 { 1444 sockaddr_in socketAddress; 1445 NetAddressToIPSocket(address, &socketAddress); 1446 1447 if (socketFd == InvalidSocketHandle) 1448 { 1449 socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET, false); 1450 } 1451 1452 if (!::connect(socketFd, (struct sockaddr *) &socketAddress, sizeof(socketAddress))) 1453 return NoError; 1454 } 1455 else if (address->type == NetAddress::IPV6Address) 1456 { 1457 sockaddr_in6 socketAddress; 1458 NetAddressToIPSocket6(address, &socketAddress); 1459 1460 if (socketFd == InvalidSocketHandle) 1461 { 1462 socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET6, false); 1463 } 1464 1465 if (!::connect(socketFd, (struct sockaddr *) &socketAddress, sizeof(socketAddress))) 1466 return NoError; 1467 } 1468 1469 return PlatformNetState::getLastError(); 1470} 1471 1472Net::Error Net::listen(NetSocket handleFd, S32 backlog) 1473{ 1474 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1475 if (socketFd == InvalidSocketHandle) 1476 return NotASocket; 1477 1478 if(!::listen(socketFd, backlog)) 1479 return NoError; 1480 return PlatformNetState::getLastError(); 1481} 1482 1483NetSocket Net::accept(NetSocket handleFd, NetAddress *remoteAddress) 1484{ 1485 sockaddr_storage addr; 1486 socklen_t addrLen = sizeof(addr); 1487 1488 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1489 if (socketFd == InvalidSocketHandle) 1490 return NetSocket::INVALID; 1491 1492 SOCKET acceptedSocketFd = ::accept(socketFd, (sockaddr *)&addr, &addrLen); 1493 if (acceptedSocketFd != InvalidSocketHandle) 1494 { 1495 if (addr.ss_family == AF_INET) 1496 { 1497 // ipv4 1498 IPSocketToNetAddress(((struct sockaddr_in*)&addr), remoteAddress); 1499 } 1500 else if (addr.ss_family == AF_INET6) 1501 { 1502 // ipv6 1503 IPSocket6ToNetAddress(((struct sockaddr_in6*)&addr), remoteAddress); 1504 } 1505 1506 NetSocket newHandleFd = PlatformNetState::smReservedSocketList.reserve(acceptedSocketFd); 1507 return newHandleFd; 1508 } 1509 1510 return NetSocket::INVALID; 1511} 1512 1513Net::Error Net::bindAddress(const NetAddress &address, NetSocket handleFd, bool useUDP) 1514{ 1515 int error = 0; 1516 sockaddr_storage socketAddress; 1517 1518 dMemset(&socketAddress, '\0', sizeof(socketAddress)); 1519 1520 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1521 if (socketFd == InvalidSocketHandle) 1522 { 1523 if (handleFd.getHandle() == -1) 1524 return NotASocket; 1525 } 1526 1527 if (address.type == NetAddress::IPAddress) 1528 { 1529 socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET, useUDP); 1530 NetAddressToIPSocket(&address, (struct sockaddr_in*)&socketAddress); 1531 error = ::bind(socketFd, (struct sockaddr*)&socketAddress, sizeof(sockaddr_in)); 1532 } 1533 else if (address.type == NetAddress::IPV6Address) 1534 { 1535 socketFd = PlatformNetState::smReservedSocketList.activate(handleFd, AF_INET6, useUDP); 1536 NetAddressToIPSocket6(&address, (struct sockaddr_in6*)&socketAddress); 1537 error = ::bind(socketFd, (struct sockaddr*)&socketAddress, sizeof(sockaddr_in6)); 1538 } 1539 1540 if (!error) 1541 return NoError; 1542 return PlatformNetState::getLastError(); 1543} 1544 1545Net::Error Net::setBufferSize(NetSocket handleFd, S32 bufferSize) 1546{ 1547 S32 error; 1548 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1549 if (socketFd == InvalidSocketHandle) 1550 return NotASocket; 1551 1552 error = ::setsockopt(socketFd, SOL_SOCKET, SO_RCVBUF, (char *) &bufferSize, sizeof(bufferSize)); 1553 if(!error) 1554 error = ::setsockopt(socketFd, SOL_SOCKET, SO_SNDBUF, (char *) &bufferSize, sizeof(bufferSize)); 1555 if(!error) 1556 return NoError; 1557 return PlatformNetState::getLastError(); 1558} 1559 1560Net::Error Net::setBroadcast(NetSocket handleFd, bool broadcast) 1561{ 1562 S32 bc = broadcast; 1563 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1564 if (socketFd == InvalidSocketHandle) 1565 return NotASocket; 1566 S32 error = ::setsockopt(socketFd, SOL_SOCKET, SO_BROADCAST, (char*)&bc, sizeof(bc)); 1567 if(!error) 1568 return NoError; 1569 return PlatformNetState::getLastError(); 1570} 1571 1572Net::Error Net::setBlocking(NetSocket handleFd, bool blockingIO) 1573{ 1574 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1575 if (socketFd == InvalidSocketHandle) 1576 return NotASocket; 1577 1578 unsigned long notblock = !blockingIO; 1579 S32 error = ioctl(socketFd, FIONBIO, ¬block); 1580 if(!error) 1581 return NoError; 1582 return PlatformNetState::getLastError(); 1583} 1584 1585Net::Error Net::getListenAddress(const NetAddress::Type type, NetAddress *address, bool forceDefaults) 1586{ 1587 if (type == NetAddress::IPAddress) 1588 { 1589 const char* serverIP = forceDefaults ? NULL : Con::getVariable("pref::Net::BindAddress"); 1590 if (!serverIP || serverIP[0] == '\0') 1591 { 1592 address->type = type; 1593 address->port = 0; 1594 *((U32*)address->address.ipv4.netNum) = INADDR_ANY; 1595 return Net::NoError; 1596 } 1597 else 1598 { 1599 return Net::stringToAddress(serverIP, address, false); 1600 } 1601 } 1602 else if (type == NetAddress::IPBroadcastAddress) 1603 { 1604 address->type = type; 1605 address->port = 0; 1606 *((U32*)address->address.ipv4.netNum) = INADDR_BROADCAST; 1607 return Net::NoError; 1608 } 1609 else if (type == NetAddress::IPV6Address) 1610 { 1611 const char* serverIP6 = forceDefaults ? NULL : Con::getVariable("pref::Net::BindAddress6"); 1612 if (!serverIP6 || serverIP6[0] == '\0') 1613 { 1614 sockaddr_in6 addr; 1615 dMemset(&addr, '\0', sizeof(addr)); 1616 1617 addr.sin6_port = 0; 1618 addr.sin6_addr = in6addr_any; 1619 1620 IPSocket6ToNetAddress(&addr, address); 1621 return Net::NoError; 1622 } 1623 else 1624 { 1625 return Net::stringToAddress(serverIP6, address, false); 1626 } 1627 } 1628 else if (type == NetAddress::IPV6MulticastAddress) 1629 { 1630 const char* multicastAddressValue = forceDefaults ? NULL : Con::getVariable("pref::Net::Multicast6Address"); 1631 if (!multicastAddressValue || multicastAddressValue[0] == '\0') 1632 { 1633 multicastAddressValue = TORQUE_NET_DEFAULT_MULTICAST_ADDRESS; 1634 } 1635 1636 return Net::stringToAddress(multicastAddressValue, address, false); 1637 } 1638 else 1639 { 1640 return Net::WrongProtocolType; 1641 } 1642} 1643 1644void Net::getIdealListenAddress(NetAddress *address) 1645{ 1646 dMemset(address, '\0', sizeof(NetAddress)); 1647 1648 if (Net::smIpv6Enabled) 1649 { 1650 if (Net::getListenAddress(NetAddress::IPV6Address, address) == NeedHostLookup) 1651 { 1652 Net::getListenAddress(NetAddress::IPV6Address, address, true); 1653 } 1654 } 1655 else 1656 { 1657 if (Net::getListenAddress(NetAddress::IPAddress, address) == NeedHostLookup) 1658 { 1659 Net::getListenAddress(NetAddress::IPAddress, address, true); 1660 } 1661 } 1662} 1663 1664Net::Error Net::send(NetSocket handleFd, const U8 *buffer, S32 bufferSize, S32 *outBytesWritten) 1665{ 1666 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1667 if (socketFd == InvalidSocketHandle) 1668 return NotASocket; 1669 1670 errno = 0; 1671 S32 bytesWritten = ::send(socketFd, (const char*)buffer, bufferSize, 0); 1672 1673 if (outBytesWritten) 1674 { 1675 *outBytesWritten = *outBytesWritten < 0 ? 0 : bytesWritten; 1676 } 1677 1678 return PlatformNetState::getLastError(); 1679} 1680 1681Net::Error Net::recv(NetSocket handleFd, U8 *buffer, S32 bufferSize, S32 *bytesRead) 1682{ 1683 SOCKET socketFd = PlatformNetState::smReservedSocketList.resolve(handleFd); 1684 if (socketFd == InvalidSocketHandle) 1685 return NotASocket; 1686 1687 *bytesRead = ::recv(socketFd, (char*)buffer, bufferSize, 0); 1688 if(*bytesRead == -1) 1689 return PlatformNetState::getLastError(); 1690 return NoError; 1691} 1692 1693bool Net::compareAddresses(const NetAddress *a1, const NetAddress *a2) 1694{ 1695 return a1->isSameAddressAndPort(*a2); 1696} 1697 1698Net::Error Net::stringToAddress(const char *addressString, NetAddress *address, bool hostLookup, int requiredFamily) 1699{ 1700 char addr[256]; 1701 int port = 0; 1702 int actualFamily = AF_UNSPEC; 1703 if (!PlatformNetState::extractAddressParts(addressString, addr, port, actualFamily)) 1704 { 1705 return WrongProtocolType; 1706 } 1707 1708 // Make sure family matches (in cast we have IP: stuff in address) 1709 if (requiredFamily != AF_UNSPEC && actualFamily != AF_UNSPEC && (actualFamily != requiredFamily)) 1710 { 1711 return WrongProtocolType; 1712 } 1713 1714 if (actualFamily == AF_UNSPEC) 1715 { 1716 actualFamily = requiredFamily; 1717 } 1718 1719 addressString = addr; 1720 dMemset(address, '\0', sizeof(NetAddress)); 1721 1722 if (!dStricmp(addressString, "broadcast")) 1723 { 1724 address->type = NetAddress::IPBroadcastAddress; 1725 if (!(actualFamily == AF_UNSPEC || actualFamily == AF_INET)) 1726 return WrongProtocolType; 1727 1728 if (port != 0) 1729 address->port = port; 1730 else 1731 address->port = PlatformNetState::defaultPort; 1732 } 1733 else if (!dStricmp(addressString, "multicast")) 1734 { 1735 address->type = NetAddress::IPV6MulticastAddress; 1736 if (!(actualFamily == AF_UNSPEC || actualFamily == AF_INET6)) 1737 return WrongProtocolType; 1738 1739 if (port != 0) 1740 address->port = port; 1741 else 1742 address->port = PlatformNetState::defaultPort; 1743 } 1744 else 1745 { 1746 sockaddr_in ipAddr; 1747 sockaddr_in6 ipAddr6; 1748 1749 dMemset(&ipAddr, 0, sizeof(ipAddr)); 1750 dMemset(&ipAddr6, 0, sizeof(ipAddr6)); 1751 1752 bool hasInterface = dStrchr(addressString, '%') != NULL; // if we have an interface, best use getaddrinfo to parse 1753 1754 // Check if we've got a simple ipv4 / ipv6 1755 1756 if (inet_pton(AF_INET, addressString, &ipAddr.sin_addr) == 1) 1757 { 1758 if (!(actualFamily == AF_UNSPEC || actualFamily == AF_INET)) 1759 return WrongProtocolType; 1760 IPSocketToNetAddress(((struct sockaddr_in*)&ipAddr), address); 1761 1762 if (port != 0) 1763 address->port = port; 1764 else 1765 address->port = PlatformNetState::defaultPort; 1766 1767 return NoError; 1768 } 1769 else if (!hasInterface && inet_pton(AF_INET6, addressString, &ipAddr6.sin6_addr) == 1) 1770 { 1771 if (!(actualFamily == AF_UNSPEC || actualFamily == AF_INET6)) 1772 return WrongProtocolType; 1773 IPSocket6ToNetAddress(((struct sockaddr_in6*)&ipAddr6), address); 1774 1775 if (port != 0) 1776 address->port = port; 1777 else 1778 address->port = PlatformNetState::defaultPort; 1779 1780 return NoError; 1781 } 1782 else 1783 { 1784 if (!hostLookup && !hasInterface) 1785 return NeedHostLookup; 1786 1787 struct addrinfo hint, *res = NULL; 1788 dMemset(&hint, 0, sizeof(hint)); 1789 hint.ai_family = actualFamily; 1790 hint.ai_flags = hostLookup ? 0 : AI_NUMERICHOST; 1791 1792 if (getaddrinfo(addressString, NULL, &hint, &res) == 0) 1793 { 1794 if (actualFamily != AF_UNSPEC) 1795 { 1796 // Prefer desired protocol 1797 res = PlatformNetState::pickAddressByProtocol(res, actualFamily); 1798 } 1799 1800 if (res && res->ai_family == AF_INET) 1801 { 1802 // ipv4 1803 IPSocketToNetAddress(((struct sockaddr_in*)res->ai_addr), address); 1804 } 1805 else if (res && res->ai_family == AF_INET6) 1806 { 1807 // ipv6 1808 IPSocket6ToNetAddress(((struct sockaddr_in6*)res->ai_addr), address); 1809 } 1810 else 1811 { 1812 // unknown 1813 return UnknownError; 1814 } 1815 1816 if (port != 0) 1817 address->port = port; 1818 else 1819 address->port = PlatformNetState::defaultPort; 1820 } 1821 } 1822 } 1823 1824 return NoError; 1825} 1826 1827void Net::addressToString(const NetAddress *address, char addressString[256]) 1828{ 1829 if(address->type == NetAddress::IPAddress || address->type == NetAddress::IPBroadcastAddress) 1830 { 1831 sockaddr_in ipAddr; 1832 NetAddressToIPSocket(address, &ipAddr); 1833 1834 if (ipAddr.sin_addr.s_addr == htonl(INADDR_BROADCAST) || address->type == NetAddress::IPBroadcastAddress) 1835 { 1836 if (ipAddr.sin_port == 0) 1837 dSprintf(addressString, 256, "IP:Broadcast"); 1838 else 1839 dSprintf(addressString, 256, "IP:Broadcast:%d", ntohs(ipAddr.sin_port)); 1840 } 1841 else 1842 { 1843 char buffer[256]; 1844 buffer[0] = '\0'; 1845 inet_ntop(AF_INET, &(ipAddr.sin_addr), buffer, sizeof(buffer)); 1846 if (ipAddr.sin_port == 0) 1847 dSprintf(addressString, 256, "IP:%s", buffer); 1848 else 1849 dSprintf(addressString, 256, "IP:%s:%i", buffer, ntohs(ipAddr.sin_port)); 1850 } 1851 } 1852 else if (address->type == NetAddress::IPV6Address) 1853 { 1854 char buffer[256]; 1855 buffer[0] = '\0'; 1856 sockaddr_in6 ipAddr; 1857 NetAddressToIPSocket6(address, &ipAddr); 1858 inet_ntop(AF_INET6, &(ipAddr.sin6_addr), buffer, sizeof(buffer)); 1859 if (ipAddr.sin6_port == 0) 1860 dSprintf(addressString, 256, "IP6:%s", buffer); 1861 else 1862 dSprintf(addressString, 256, "IP6:[%s]:%i", buffer, ntohs(ipAddr.sin6_port)); 1863 } 1864 else if (address->type == NetAddress::IPV6MulticastAddress) 1865 { 1866 if (address->port == 0) 1867 dSprintf(addressString, 256, "IP6:Multicast"); 1868 else 1869 dSprintf(addressString, 256, "IP6:Multicast:%d", address->port); 1870 } 1871 else 1872 { 1873 *addressString = 0; 1874 return; 1875 } 1876} 1877 1878void Net::enableMulticast() 1879{ 1880 SOCKET socketFd; 1881 1882 if (Net::smIpv6Enabled) 1883 { 1884 socketFd = PlatformNetState::smReservedSocketList.resolve(PlatformNetState::udp6Socket); 1885 1886 if (socketFd != InvalidSocketHandle) 1887 { 1888 PlatformNetState::multicast6Socket = PlatformNetState::udp6Socket; 1889 1890 Net::Error error = NoError; 1891 1892 if (error == NoError) 1893 { 1894 unsigned long multicastTTL = 1; 1895 1896 if (setsockopt(socketFd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 1897 (char*)&multicastTTL, sizeof(multicastTTL)) < 0) 1898 { 1899 error = PlatformNetState::getLastError(); 1900 } 1901 } 1902 1903 // Find multicast to bind to... 1904 1905 NetAddress multicastAddress; 1906 sockaddr_in6 multicastSocketAddress; 1907 1908 const char *multicastAddressValue = Con::getVariable("pref::Net::Multicast6Address"); 1909 if (!multicastAddressValue || multicastAddressValue[0] == '\0') 1910 { 1911 multicastAddressValue = TORQUE_NET_DEFAULT_MULTICAST_ADDRESS; 1912 } 1913 1914 error = Net::stringToAddress(multicastAddressValue, &multicastAddress, false); 1915 1916 if (error == NoError) 1917 { 1918 dMemset(&PlatformNetState::multicast6Group, '\0', sizeof(&PlatformNetState::multicast6Group)); 1919 NetAddressToIPSocket6(&multicastAddress, &multicastSocketAddress); 1920 dMemcpy(&PlatformNetState::multicast6Group.ipv6mr_multiaddr, &multicastSocketAddress.sin6_addr, sizeof(PlatformNetState::multicast6Group.ipv6mr_multiaddr)); 1921 } 1922 1923 // Setup group 1924 1925 if (error == NoError) 1926 { 1927 const char *multicastInterface = Con::getVariable("pref::Net::Multicast6Interface"); 1928 1929 if (multicastInterface && multicastInterface[0] != '\0') 1930 { 1931#ifdef TORQUE_USE_WINSOCK 1932 PlatformNetState::multicast6Group.ipv6mr_interface = dAtoi(multicastInterface); 1933#else 1934 PlatformNetState::multicast6Group.ipv6mr_interface = if_nametoindex(multicastInterface); 1935#endif 1936 } 1937 else 1938 { 1939 PlatformNetState::multicast6Group.ipv6mr_interface = 0; // 0 == accept from any interface 1940 } 1941 1942 if (PlatformNetState::multicast6Group.ipv6mr_interface && error == NoError) 1943 { 1944 if (setsockopt(socketFd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&PlatformNetState::multicast6Group.ipv6mr_interface, sizeof(PlatformNetState::multicast6Group.ipv6mr_interface)) < 0) 1945 { 1946 error = PlatformNetState::getLastError(); 1947 } 1948 } 1949 1950 if (error == NoError && setsockopt(socketFd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char*)&PlatformNetState::multicast6Group, sizeof(PlatformNetState::multicast6Group)) < 0) 1951 { 1952 error = PlatformNetState::getLastError(); 1953 } 1954 } 1955 1956 1957 if (error == NoError) 1958 { 1959 char listenAddressStr[256]; 1960 Net::addressToString(&multicastAddress, listenAddressStr); 1961 Con::printf("Multicast initialized on %s", listenAddressStr); 1962 } 1963 1964 if (error != NoError) 1965 { 1966 PlatformNetState::multicast6Socket = NetSocket::INVALID; 1967 Con::printf("Unable to multicast UDP - error %d", error); 1968 } 1969 } 1970 } 1971} 1972 1973void Net::disableMulticast() 1974{ 1975 if (PlatformNetState::multicast6Socket != NetSocket::INVALID) 1976 { 1977 PlatformNetState::multicast6Socket = NetSocket::INVALID; 1978 } 1979} 1980 1981bool Net::isMulticastEnabled() 1982{ 1983 return PlatformNetState::multicast6Socket != NetSocket::INVALID; 1984} 1985 1986U32 NetAddress::getHash() const 1987{ 1988 U32 value = 0; 1989 switch (type) 1990 { 1991 case NetAddress::IPAddress: 1992 value = Torque::hash((const U8*)&address.ipv4.netNum, sizeof(address.ipv4.netNum), 0); 1993 break; 1994 case NetAddress::IPV6Address: 1995 value = Torque::hash((const U8*)address.ipv6.netNum, sizeof(address.ipv6.netNum), 0); 1996 break; 1997 default: 1998 value = 0; 1999 break; 2000 } 2001 return value; 2002} 2003 2004bool Net::isAddressTypeAvailable(NetAddress::Type addressType) 2005{ 2006 switch (addressType) 2007 { 2008 case NetAddress::IPAddress: 2009 return PlatformNetState::udpSocket != NetSocket::INVALID; 2010 case NetAddress::IPV6Address: 2011 return PlatformNetState::udp6Socket != NetSocket::INVALID; 2012 case NetAddress::IPBroadcastAddress: 2013 return PlatformNetState::udpSocket != NetSocket::INVALID; 2014 case NetAddress::IPV6MulticastAddress: 2015 return PlatformNetState::multicast6Socket != NetSocket::INVALID; 2016 default: 2017 return false; 2018 } 2019} 2020