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