uint16_t UDPNetworkSocket::getPort() const { if(data->port > 0) return data->port; #ifdef UTIL_HAVE_LIB_SDL2_NET IPaddress* sdlAddress = SDLNet_UDP_GetPeerAddress(data->udpsock, -1); if(!sdlAddress) { std::cerr << "SDLNet_UDP_GetPeerAddress: " << SDLNet_GetError() << "\n"; return 0; } IPv4Address address = fromSDLIPv4Address(*sdlAddress); return address.getPort(); #elif defined(__linux__) || defined(__unix__) || defined(ANDROID) struct sockaddr_in localAddress; socklen_t addressLength = sizeof(localAddress); if(getsockname(data->udpSocket, reinterpret_cast<struct sockaddr*>(&localAddress), &addressLength)) { int error = errno; WARN(std::string(strerror(error))); return 0; } IPv4Address address = fromSockaddr(localAddress); return address.getPort(); #else return 0; #endif }
IPaddress* network_get_peer_address(UDPsocket udp, int channel) { IPaddress* ipa = NULL; ipa = SDLNet_UDP_GetPeerAddress(udp, channel); if (ipa == NULL) { std::cerr << "Failed to get UDP peer address: " << SDLNet_GetError() << "\n"; return NULL; } return ipa; }
/* * network_get_peer_address() - Return the IP data of the remote UDP connection * @udp: the remote connection to return data for * @channel: the channel of the remote connection */ IPaddress* network_get_peer_address(UDPsocket udp, int channel) { IPaddress* ipa = nullptr; // Declare an IP data struct ipa = SDLNet_UDP_GetPeerAddress(udp, channel); // Attempt to get the peer address info if (ipa == nullptr) { // If the information could not be retrieved std::cerr << "Failed to get UDP peer address: " << SDLNet_GetError() << "\n"; // Output the error message } return ipa; // Return the IP data on success }
void Peer::pSock() const { for (unsigned int s = 0; s < sockets.size(); s++) // socket { for (unsigned int c = 0; c < (SDLNET_MAX_UDPCHANNELS-1); c++) // channel { // get the peer assigned to that socket and channel IPaddress *peer = SDLNet_UDP_GetPeerAddress(sockets[s],c); // if there is a peer on that socket and channel if (peer != nullptr) { Print("%s, %s: %s\n", std::to_string(s), std::to_string(c), std::to_string(peer->host)); } else Print("%s, %s : empty\n", std::to_string(s), std::to_string(c)); } } }
int Peer::GetPeerCount() const { int count = 0; for (unsigned int s = 0;s<sockets.size(); s++) // socket { for (unsigned int c = 0; c < (SDLNET_MAX_UDPCHANNELS-1); c++) // channel { // get the peer assigned to that socket and channel IPaddress *peer = SDLNet_UDP_GetPeerAddress(sockets[s],c); //BUG: If a peer is connected on more then one socket / channel then they will be counted more then once. // if there is a peer on that socket and channel if (peer != nullptr) { count++; } } } return count; }
std::tuple<int, int> Peer::GetRemotePeer(const IPaddress *address) const { for (unsigned int s = 0;s<sockets.size(); s++) // socket { for (unsigned int c = 0; c < (SDLNET_MAX_UDPCHANNELS-1); c++) // channel { // get the peer assigned to that socket and channel IPaddress *peer = SDLNet_UDP_GetPeerAddress(sockets[s],c); // if there is a peer on that socket and channel if (peer != nullptr) { // is their IP the same as the one we are looking for? Print("looking for: %s : %s", getIP(address->host), getIP(peer->host)); if (getIP(peer->host) == getIP(address->host)) { //if yes, return socket and channel return std::make_tuple(s,c); } } } } return std::make_tuple(-1,-1); }
IPaddress UDP_Socket::peer_address() const { return *SDLNet_UDP_GetPeerAddress(sock, -1); }
bool Client::Init () { #ifdef CONFDIR settingsPath = std::string (CONFDIR) + PATH_SEPARATOR + "client.ini"; #else settingsPath = std::string (SDL_GetBasePath()) + "settings.ini"; #endif // initialize SDL_net: char hostName [100]; int port, w, h; if (!LoadSettingString (settingsPath.c_str (), HOST_SETTING, hostName)) { SetError ("cannot read \'%s\' from %s", HOST_SETTING, settingsPath.c_str ()); return false; } if ((port = LoadSetting (settingsPath.c_str (), PORT_SETTING)) <= 0) { SetError ("cannot read \'%s\' from %s", PORT_SETTING, settingsPath.c_str ()); return false; } if (SDLNet_Init () < 0) { SetError ("SDLNet_Init: %s", SDLNet_GetError()); return false; } if (!(udp_socket = SDLNet_UDP_Open (0))) // the client can run on a random port { SetError ("SDLNet_UDP_Open: %s", SDLNet_GetError()); return false; } if (SDLNet_ResolveHost (&serverAddress, hostName, port) == -1) { SetError ("SDLNet_ResolveHost with hostname %s and port %d: %s", hostName, port, SDLNet_GetError()); return false; } if (!(pUDPAddress = SDLNet_UDP_GetPeerAddress (udp_socket, -1))) { SetError ("SDLNet_UDP_GetPeerAddress from own udp socket: %s", SDLNet_GetError()); return false; } if(!(udpPackets = SDLNet_AllocPacketV(2, PACKET_MAXSIZE))) { SetError ("SDLNet_AllocPacketV: %s", SDLNet_GetError()); return false; } toServer = udpPackets[0]; fromServer = udpPackets[1]; // initialize SDL with screen sizes from settings file: w = LoadSetting (settingsPath.c_str (), SCREENWIDTH_SETTING); if (w <= 0) w = 800; h = LoadSetting (settingsPath.c_str (), SCREENHEIGHT_SETTING); if (h <= 0) h = 600; fullscreen = LoadSetting (settingsPath.c_str (), FULLSCREEN_SETTING) > 0 ? true : false; int error = SDL_Init (SDL_INIT_EVERYTHING); if (error != 0) { SetError ("Unable to initialize SDL: %s", SDL_GetError()); return false; } SDL_StartTextInput (); // Set the openGL parameters we want: SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, 4); Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL ; if (fullscreen) flags |= SDL_WINDOW_FULLSCREEN | SDL_WINDOW_INPUT_GRABBED; mainWindow = SDL_CreateWindow (WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, flags); if (!mainWindow) { SetError ("SDL_CreateWindow failed: %s", SDL_GetError()); return false; } #ifdef _WIN32 /* In windows executables, the icon is simply included. However, we must still attach it to the window. */ SDL_SysWMinfo wm_info; SDL_VERSION (&wm_info.version); if (!SDL_GetWindowWMInfo (mainWindow, &wm_info)) { SetError ("SDL_GetWindowWMInfo failed: %s", SDL_GetError()); return false; } HINSTANCE hInstance = GetModuleHandle (NULL); icon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON)); // Set the icon for the window SendMessage (wm_info.info.win.window, WM_SETICON, ICON_SMALL, (LPARAM) icon); // Set the icon in the task manager SendMessage (wm_info.info.win.window, WM_SETICON, ICON_BIG, (LPARAM) icon); #endif mainGLContext = SDL_GL_CreateContext(mainWindow); if (!mainGLContext) { SetError ("Failed to create GL context: %s", SDL_GetError ()); return false; } // We use glew to check if our openGL version is at least 2.0 GLenum err = glewInit(); if (GLEW_OK != err) { SetError ("glewInit failed: %s", glewGetErrorString(err)); return false; } if(!GL_VERSION_2_0) { SetError ("OpenGL version 2.0 is not enabled."); return false; } // See if nothing went wrong: if (!CheckGLOK("GL init")) return false; // Initialize SDL_mixer, check if audio is enabled. has_audio = (Mix_OpenAudio (44100, MIX_DEFAULT_FORMAT, 2, 1024) == 0); if (!has_audio) SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Warning: Cannot open Audio", Mix_GetError(), NULL); SDL_ShowCursor (0); // Initialize the login scene pScene = new LoginScene (this); if (!pScene->Init()) return false; return true; }
/** * @brief Adds remote peer or finds via DNS * * @param address Address to add * @param port Port to connect to * @param outport Port to connect on * @return 0 on fail, 1 on success, 2 if already bound */ int Peer::AddRemotePeer(const std::string address, const int port, const int outport) { IPaddress ip; ip.port = port; Print("resolving host...\n"); if (SDLNet_ResolveHost(&ip, address.c_str(), 0)==-1) { Print("Some DNS requests require more then one request before you will get a response!\n"); return 0; } Print("found dns match: %s\n", getIP(ip.host)); Print("checking for avaliable sockets...\n"); //Do we have any sockets? if (sockets.size()) { //if no, add one if (!addSocket(outport)) { //if we failed to add one, return return 0; } } // try and see if this peer already has a socket / channel bound Print("crosschecking with current peers...\n"); auto gp = GetRemotePeer(&ip); if (std::get<0>(gp)!=-1 && std::get<1>(gp)!=-1) { return 2; // if already bound then return 2 } Print("finding an empty socket channel...\n"); //TODO: write a function that finds an empty socket/channel maybe // find an empty channel to bind the peer to for (UDPsocket &sock : sockets) { if (outport) // if we want a specific outport { // and the socket we are checking is not our desired port Uint16 port = SDLNet_UDP_GetPeerAddress(sock,-1)->port; if (SDLNet_Read16(&port) != outport) continue; // skip this iteration } for ( int i = 0; i < (SDLNET_MAX_UDPADDRESSES-1); i++) { IPaddress *peer = SDLNet_UDP_GetPeerAddress(sock,i); if (!peer) { Print("Found an empty sock / channel\n"); int channel = SDLNet_UDP_Bind(sock, i, &ip); if (channel == -1) { Print("SDLNet_UDP_Bind: %s\n", SDLNet_GetError()); return 0; // Failed to bind } else { Print("BOUND\n"); return 1; // Bound! } } } } Print("none found, adding a new socket and trying again...\n"); // if no empty channel found, add socket and try again if (!addSocket(outport)) { //if we failed to add one, return return 0; } for (UDPsocket &sock : sockets) { if (outport) // if we want a specific outport { // and the socket we are checking is not our desired port Uint16 port = SDLNet_UDP_GetPeerAddress(sock,-1)->port; if (SDLNet_Read16(&port) != outport){ continue; // skip this iteration } } for ( int i = 0; i < (SDLNET_MAX_UDPADDRESSES-1); i++) { IPaddress *peer = SDLNet_UDP_GetPeerAddress(sock, i); if (!peer) { Print("Found an empty sock / channel\n"); int channel = SDLNet_UDP_Bind(sock, i, &ip); if (channel == -1) { Print("SDLNet_UDP_Bind: %s\n", SDLNet_GetError()); return 0; // Failed to bind } else { Print("BOUND\n"); return 1; // Bound! } } } } Print("did not bind.\n"); return 0; //for (IPaddress & ip : SDLNet_UDP_GetPeerAddress(,-1)) }
IPaddress* GetIPAddress(int channel) { return SDLNet_UDP_GetPeerAddress(socket, channel); }