1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-07-02 16:38:41 +00:00

Alternative Solution for lan_adv Destructer

This commit is contained in:
DustyBagel 2024-07-07 21:00:33 -05:00
parent fac62dc3d1
commit 7e78a5ece0
4 changed files with 103 additions and 93 deletions

View file

@ -392,8 +392,6 @@ local function main_button_handler(tabview, fields, name, tabdata)
serverlistmgr.add_favorite(server)
print("Adding this server to favorites: \n"..dump(server))
gamedata.servername = server.name
gamedata.serverdescription = server.description

View file

@ -78,24 +78,6 @@ lan_adv::lan_adv() : Thread("lan_adv")
{
}
lan_adv::~lan_adv()
{
if (!stopRequested()) {
stop();
warningstream << "Thread Had to be forced to stop correctly." << std::endl;
}
if (stopRequested()) warningstream << "Lan Adv Thread is stopping." << std::endl;
if (server_port) {
Json::Value answer_json;
answer_json["port"] = server_port;
answer_json["cmd"] = "shutdown";
send_string(fastWriteJson(answer_json));
warningstream << "Server shut down message sent." << std::endl;
}
}
void lan_adv::ask()
{
if (!isRunning()) start();
@ -111,35 +93,7 @@ void lan_adv::ask()
void lan_adv::send_string(const std::string &str)
{
try {
sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = htons(adv_port);
UDPSocket socket_send(false);
// Full discloser, the use of inet_proto and the mreq stucture
// were suggested by ai.
inet_pton(AF_INET, adv_multicast_addr, &(addr.sin_addr));
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(adv_multicast_addr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(socket_send.GetHandle(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
(const char *)&mreq, sizeof(mreq));
//int set_option_on = 2;
//setsockopt(socket_send.GetHandle(), SOL_SOCKET, IP_MULTICAST_TTL,
// (const char *)&set_option_on, sizeof(set_option_on));
socket_send.Send(Address(addr), str.c_str(), str.size());
} catch (const std::exception &e) {
verbosestream << "udp broadcast send4 fail " << e.what() << "\n";
}
if (g_settings->getBool("enable_ipv6")) {
std::vector<uint32_t> scopes;
// todo: windows and android
@ -195,13 +149,43 @@ void lan_adv::send_string(const std::string &str)
socket_send.Send(Address(addr), str.c_str(), str.size());
}
} catch (const std::exception &e) {
verbosestream << "udp broadcast send6 fail " << e.what() << "\n";
verbosestream << "udp broadcast send over ipv6 fail " << e.what() << "\n";
}
}
freeaddrinfo(result);
}
}
try {
sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = htons(adv_port);
UDPSocket socket_send(false);
// Full discloser, the use of inet_proto and the mreq stucture
// were suggested by ai.
inet_pton(AF_INET, adv_multicast_addr, &(addr.sin_addr));
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(adv_multicast_addr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(socket_send.GetHandle(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
(const char *)&mreq, sizeof(mreq));
//int set_option_on = 2;
//setsockopt(socket_send.GetHandle(), SOL_SOCKET, IP_MULTICAST_TTL,
// (const char *)&set_option_on, sizeof(set_option_on));
socket_send.Send(Address(addr), str.c_str(), str.size());
} catch (const std::exception &e) {
verbosestream << "udp broadcast send over ipv4 fail " << e.what() << "\n";
}
}
void lan_adv::serve(unsigned short port)
{
server_port = port;
@ -213,9 +197,9 @@ void *lan_adv::run()
{
BEGIN_DEBUG_EXCEPTION_HANDLER;
setName("LanAdv" + (server_port ? std::string("Server") : std::string("Client")));
setName("lan_adv " + (server_port ? std::string("server") : std::string("client")));
UDPSocket socket_recv(g_settings->getBool("enable_ipv6"));
UDPSocket socket_recv(true);
int set_option_off = 0, set_option_on = 1;
setsockopt(socket_recv.GetHandle(), SOL_SOCKET, SO_REUSEADDR,
(const char *)&set_option_on, sizeof(set_option_on));
@ -233,6 +217,8 @@ void *lan_adv::run()
setsockopt(socket_recv.GetHandle(), IPPROTO_IPV6, IPV6_V6ONLY,
(const char *)&set_option_off, sizeof(set_option_off));
socket_recv.setTimeoutMs(200);
if (g_settings->getBool("enable_ipv6")) {
try {
socket_recv.Bind(Address(in6addr_any, adv_port));
} catch (const std::exception &e) {
@ -246,6 +232,15 @@ void *lan_adv::run()
return nullptr;
}
}
} else {
try {
socket_recv.Bind(Address((u32)INADDR_ANY, adv_port));
} catch (const std::exception &e) {
warningstream << m_name << ": cant bind ipv4 [" << e.what() << "]"
<< std::endl;
return nullptr;
}
}
std::unordered_map<std::string, uint64_t> limiter;
const unsigned int packet_maxsize = 16384;
char buffer[packet_maxsize];
@ -273,7 +268,7 @@ void *lan_adv::run()
send_string(fastWriteJson(server));
}
while (!stopRequested()) {
while (isRunning() && !stopRequested()) {
BEGIN_DEBUG_EXCEPTION_HANDLER;
Address addr;
int rlen = socket_recv.Receive(addr, buffer, packet_maxsize);
@ -325,6 +320,13 @@ void *lan_adv::run()
END_DEBUG_EXCEPTION_HANDLER;
}
if (server_port) {
Json::Value answer_json;
answer_json["port"] = server_port;
answer_json["cmd"] = "shutdown";
send_string(fastWriteJson(answer_json));
}
END_DEBUG_EXCEPTION_HANDLER;
return nullptr;

View file

@ -32,7 +32,6 @@ public:
void *run();
lan_adv();
~lan_adv();
void ask();
void send_string(const std::string &str);

View file

@ -412,6 +412,17 @@ Server::~Server()
delete m_unsent_map_edit_queue.front();
m_unsent_map_edit_queue.pop();
}
if (g_settings->getBool("serverlist_lan")) {
lan_adv_server.stop();
while (lan_adv_server.isRunning()) {
// Wait until the lan_adv_server thread has finished.
// This is so that its thread destructor doesn't kill the thread
// before it sends the 'shutdown' command to remove this server's
// server info from the serverlist of local clients.
}
}
}
void Server::init()