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