NetAddress Socket::getsockname() { char buf[sizeof(sockaddr_in) + 1]; memset(buf, 0, sizeof(buf)); socklen_t len = sizeof(buf); int ret = ::getsockname(fd(), (sockaddr*)buf, &len); setStatus(); return NetAddress(buf, len); }
NetListener::NetListener(uint16 port) { NetworkDevice* nd = NetworkDevice::instance(); // Start the listener socket Log::common()->print("Creating a listener "); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (sock == SOCKET_ERROR) { Log::common()->printf("FAIL"); Log::common()->println(socketErrorCode()); return; } Log::common()->println("Ok"); const int T = true; // Set reuse address so that a new server can start up soon after // an old one has closed. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&T, sizeof(T)) == SOCKET_ERROR) { Log::common()->println("WARNING: Setting socket reuseaddr failed."); Log::common()->println(socketErrorCode()); } else { Log::common()->println("Set socket option reuseaddr."); } if (! nd->bind(sock, NetAddress(0, port))) { Log::common()->printf("Unable to bind!\n"); nd->closesocket(sock); sock = (SOCKET)SOCKET_ERROR; return; } Log::common()->printf("Listening on port %5d ", port); // listen is supposed to return 0 when there is no error. // The 2nd argument is the number of connections to allow pending // at any time. int L = listen(sock, 100); if (L == SOCKET_ERROR) { Log::common()->println("FAIL"); Log::common()->println(socketErrorCode()); nd->closesocket(sock); sock = (SOCKET)SOCKET_ERROR; return; } Log::common()->println("Ok"); Log::common()->printf("Now listening on socket %d.\n\n", sock); }
NetAddress Socket::getpeername() { char buf[sizeof(sockaddr_in) + 1]; memset(buf, 0, sizeof(buf)); socklen_t len = sizeof(buf); int ret = ::getpeername(fd(), (sockaddr*)&buf, &len); /// Fix a fatal bug /// setStatus(); return NetAddress(buf, len); }
ReliableConduitRef NetListener::waitForConnection() { // The address of the connecting host SOCKADDR_IN remote_addr; int iAddrLen = sizeof(remote_addr); if (nd->debugLog) { nd->debugLog->println("Blocking in NetListener::waitForConnection()."); } SOCKET sClient = accept(sock, (struct sockaddr*) &remote_addr, (socklen_t*)&iAddrLen); if (sClient == SOCKET_ERROR) { if (nd->debugLog) { nd->debugLog->println("Error in NetListener::acceptConnection."); nd->debugLog->println(socketErrorCode()); } nd->closesocket(sock); return NULL; } if (nd->debugLog) { nd->debugLog->printf("%s connected, transferred to socket %d.\n", inet_ntoa(remote_addr.sin_addr), sClient); } #ifndef G3D_WIN32 return new ReliableConduit(nd, sClient, NetAddress(htonl(remote_addr.sin_addr.s_addr), ntohs(remote_addr.sin_port))); #else return new ReliableConduit(nd, sClient, NetAddress(ntohl(remote_addr.sin_addr.S_un.S_addr), ntohs(remote_addr.sin_port))); #endif }
LightweightConduit::LightweightConduit( NetworkDevice* _nd, uint16 port, bool enableReceive, bool enableBroadcast) : Conduit(_nd) { if (nd->debugLog) {nd->debugLog->print("Creating a UDP socket ");} sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock == SOCKET_ERROR) { sock = 0; if (nd->debugLog) { nd->debugLog->println("FAIL"); nd->debugLog->println(socketErrorCode()); } return; } if (nd->debugLog) {nd->debugLog->println("Ok");} if (enableReceive) { debugAssert(port != 0); nd->bind(sock, NetAddress(0, port)); } // Figuring out the MTU seems very complicated, so we just set it to 1000, // which is likely to be safe. See IP_MTU for more information. MTU = 1000; increaseBufferSize(sock, nd->debugLog); if (enableBroadcast) { int TR = true; if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&TR, sizeof(TR)) != 0) { if (nd->debugLog) { nd->debugLog->println("Call to setsockopt failed"); nd->debugLog->println(socketErrorCode()); } nd->closesocket(sock); return; } } if (nd->debugLog) { nd->debugLog->printf("Done creating UDP socket %d\n", sock); } alreadyReadMessage = false; }
Server::Server(const ServerDescription& description, const Settings& settings) : m_settings(settings), m_description(description) { const Array<uint32> ipArray = NetworkDevice::instance()->broadcastAddressArray(); m_broadcastAddressArray.resize(ipArray.size()); for (int i = 0; i < m_broadcastAddressArray.size(); ++i) { m_broadcastAddressArray[i] = NetAddress(ipArray[i], m_settings.serverBroadcastPort); } m_net = LightweightConduit::create(m_settings.clientBroadcastPort, true, true); debugAssert(m_settings.serverAdvertisementPeriod > 0); sendAdvertisement(); }
void NetworkDevice::localHostAddresses(Array<NetAddress>& array) const { array.resize(0); char ac[256]; if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) { Log::common()->printf("Error while getting local host name\n"); return; } struct hostent* phe = gethostbyname(ac); if (phe == 0) { Log::common()->printf("Error while getting local host address\n"); return; } for (int i = 0; (phe->h_addr_list[i] != 0); ++i) { struct in_addr addr; memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr)); array.append(NetAddress(addr)); } }
void runServer() { NetworkDevice* nd = NetworkDevice::instance(); alwaysAssertM(nd->adapterArray().size() > 0, "No network adapters."); Discovery::ServerDescription description; description.applicationName = "My Game"; description.maxClients = 10; description.serverName = "My Server (" + nd->localHostName() + ")"; description.applicationAddress = NetAddress(nd->adapterArray()[0].ip, GAME_PORT); Discovery::Server::Ref discoveryServer = Discovery::Server::create(description); // DiscoverServer is a Widget, so in a GApp you can just call // GApp::addWidget() instead of explicitly running the following // loop. debugPrintf("Running server (press any key to exit)\n"); while (! System::consoleKeyPressed()) { discoveryServer->onNetwork(); System::sleep(1.0f / 30.0f); } }
bool NetworkDevice::init() { debugAssert(! initialized); logPrintf("Network Startup"); logPrintf("Starting WinSock networking.\n"); // G3D now initializes winsock through ENet // WSADATA wsda; // WSAStartup(MAKEWORD(G3D_WINSOCK_MAJOR_VERSION, G3D_WINSOCK_MINOR_VERSION), &wsda); std::string hostname = "localhost"; { char ac[128]; if (gethostname(ac, sizeof(ac)) == -1) { logPrintf("Warning: Error while getting local host name\n"); } else { hostname = gethostbyname(ac)->h_name; } } EthernetAdapter a; a.hostname = hostname; a.name = ""; a.ip = NetAddress(hostname, 0).ip(); // TODO: Find subnet on Win32 a.subnet = 0x0000FFFF; // TODO: Find broadcast on Win32 a.broadcast = 0xFFFFFFFF; // TODO: find MAC on Win32 addAdapter(a); std::string machine = localHostName(); std::string addr = NetAddress(machine, 0).ipString(); /* logPrintf( "Network:\n" " Status: %s\n" " Loaded winsock specification version %d (%d is " "the highest available)\n" " %d sockets available\n" " Largest UDP datagram packet size is %d bytes\n\n", wsda.szDescription, wsda.szSystemStatus, wsda.wVersion, wsda.wHighVersion, wsda.iMaxSockets, wsda.iMaxUdpDg); */ // TODO: WSAIoctl for subnet and broadcast addresses // http://msdn.microsoft.com/en-us/library/ms741621(VS.85).aspx // // TODO: SIO_GET_INTERFACE_LIST initialized = true; return true; }
bool NetworkDevice::init(G3D::Log* _log) { debugAssert(!initialized); debugLog = _log; #ifdef G3D_WIN32 if (debugLog) { debugLog->section("Network Startup"); debugLog->println("Starting WinSock networking.\n"); } WSADATA wsda; WSAStartup(MAKEWORD(G3D_WINSOCK_MAJOR_VERSION, G3D_WINSOCK_MINOR_VERSION), &wsda); if (debugLog) { std::string machine = localHostName(); std::string addr = NetAddress(machine, 0).ipString(); debugLog->printf( "Network:\n" " localhost = %s (%s)\n" " %s\n" " Status: %s\n" " Loaded winsock specification version %d (%d is " "the highest available)\n" " %d sockets available\n" " Largest UDP datagram packet size is %d bytes\n\n", machine.c_str(), addr.c_str(), wsda.szDescription, wsda.szSystemStatus, wsda.wVersion, wsda.wHighVersion, wsda.iMaxSockets, wsda.iMaxUdpDg); } #endif if (debugLog) {debugLog->section("Testing Network");} SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (debugLog) {debugLog->print("Open Socket ");} if (sock == SOCKET_ERROR) { if (debugLog) { debugLog->println("FAIL"); debugLog->println(socketErrorCode()); } return false; } if (debugLog) { debugLog->println("Ok"); } int TR = true; int ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&TR, sizeof(TR)); if (debugLog) {debugLog->print("Enable UDP Broadcast ");} if (ret != 0) { if (debugLog) { debugLog->println("FAIL"); debugLog->println(socketErrorCode()); } return false; } if (debugLog) {debugLog->println("Ok");} if (debugLog) {debugLog->print("Testing UDP Broadcast ");} SOCKADDR_IN addr; int32 x; addr = NetAddress(0xFFFFFFFF, 23).addr; ret = sendto(sock, (const char*)&x, sizeof(x), 0, (struct sockaddr *) &addr, sizeof(addr)); if (ret == SOCKET_ERROR) { if (debugLog) { debugLog->println("FAIL"); debugLog->println(socketErrorCode()); } return false; } if (debugLog) {debugLog->println("Ok");} if (debugLog) {debugLog->section("");} initialized = true; return true; }
NetAddress NetAddress::broadcastAddress(uint16 port) { return NetAddress(NetworkDevice::instance()->broadcastAddressArray()[0], port); }