12 #include <fc_config.h>
20 #include <QNetworkAccessManager>
21 #include <QNetworkReply>
33 #include "fc_version.h"
69 connect(
this, &QUdpSocket::readyRead,
this,
71 connect(
this, &QAbstractSocket::errorOccurred,
this,
97 errstr = errorString().toLocal8Bit().data();
120 enum QHostAddress::SpecialAddress address_type;
132 address_type = QHostAddress::AnyIPv6;
136 address_type = QHostAddress::AnyIPv4;
140 QAbstractSocket::ReuseAddressHint)) {
144 joinMulticastGroup(QHostAddress(group));
149 writeDatagram(QByteArray(buffer,
size), QHostAddress(group),
151 scan->
servers = server_list_new();
158 while (hasPendingDatagrams()) {
160 QNetworkDatagram qn = receiveDatagram();
162 QByteArray d1 = d.data();
163 QByteArray d2 = qn.data();
164 if (d1.data() == d2.data()) {
182 char servername[512];
190 bool found_new =
false;
195 if (datagram.isNull() || !datagram.isValid()) {
198 auto data = datagram.data();
207 port = atoi(portstr);
221 datagram.senderAddress().toString().toLocal8Bit());
224 log_debug(
"Received a valid announcement from a server on the LAN.");
237 server_list_prepend(scan->
servers, pserver);
252 struct server_list *server_list;
255 const char *latest_ver;
266 "version_comments." FOLLOWTAG);
268 if (latest_ver !=
nullptr) {
272 qDebug(
"Metaserver says latest '" FOLLOWTAG
273 "' version is '%s'; we have '%s'",
274 latest_ver, my_comparable);
275 if (cvercmp_greater(latest_ver, my_comparable)) {
276 const char *
const followtag =
"?vertag:" FOLLOWTAG;
281 _(
"Latest %s release of Freeciv21 is %s, this is %s."),
282 Q_(followtag), latest_ver, my_comparable);
285 }
else if (comment ==
nullptr) {
287 _(
"There is no newer %s release of Freeciv21 available."),
294 if (comment !=
nullptr) {
295 qDebug(
"Mesaserver comment about '" FOLLOWTAG
"': %s", comment);
299 server_list = server_list_new();
302 for (i = 0; i < nservers; i++) {
303 const char *host, *port, *version, *state, *
message, *nplayers, *nhumans;
336 for (j = 0; j < pserver->
nplayers; j++) {
337 const char *
name, *nation, *type, *plrhost;
348 "server%d.player%d.host", i, j);
352 "server%d.player%d.nation", i, j);
356 server_list_append(server_list, pserver);
370 struct server_list *srvrs;
372 auto *f =
new QBuffer(&scan->
meta.
mem);
373 f->open(QIODevice::ReadWrite);
382 if (
nullptr == srvrs) {
384 _(
"Failed to parse the metaserver data from %s:\n"
424 auto *manager =
new QNetworkAccessManager;
428 post.addQueryItem(QStringLiteral(
"client_cap"),
432 request.setHeader(QNetworkRequest::UserAgentHeader,
434 request.setHeader(QNetworkRequest::ContentTypeHeader,
435 QLatin1String(
"application/x-www-form-urlencoded"));
437 manager->post(request, post.toString(QUrl::FullyEncoded).toUtf8());
443 QObject::connect(reply, &QNetworkReply::finished, [&] {
444 if (reply->error() == QNetworkReply::NoError) {
445 scan->meta.mem = reply->readAll();
448 scan->error_func(scan, _(
"Error connecting to metaserver"));
449 qCritical(_(
"Error message: %s"),
450 qUtf8Printable(reply->errorString()));
452 scan->meta.mem.clear();
457 reply->deleteLater();
458 manager->deleteLater();
482 int n = ptmp->nplayers;
485 delete[] ptmp->version;
486 delete[] ptmp->state;
487 delete[] ptmp->message;
490 for (i = 0; i < n; i++) {
491 delete[] ptmp->players[i].name;
492 delete[] ptmp->players[i].type;
493 delete[] ptmp->players[i].host;
494 delete[] ptmp->players[i].nation;
496 delete[] ptmp->players;
503 server_list_destroy(server_list);
575 switch (scan->
type) {
const char *const our_capability
void version_message(const QString &vertext)
Got version message from metaserver.
QList< QNetworkDatagram > datagram_list
fcUdpScan(QObject *parent=0)
static fcUdpScan * i()
returns fcUdpScan instance, use it to initizalize fcUdpScan or for calling methods
static void drop()
deletes fcUdpScan
bool begin_scan(struct server_scan *scan)
Broadcast an UDP package to all servers on LAN, requesting information about the server.
void readPendingDatagrams()
enum server_scan_status get_server_list(struct server_scan *scan)
Listens for UDP packets broadcasted from a server that responded to the request-packet sent from the ...
struct server_scan * fcudp_scan
static fcUdpScan * m_instance
void sockError(QAbstractSocket::SocketError socketError)
Pass errors to main scan.
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
Initializes the output to the given output buffer and the given buffer size.
void dio_put_uint8_raw(struct raw_data_out *dout, int value)
Insert value using 8 bits.
bool dio_get_uint8_raw(struct data_in *din, int *dest)
Receive uint8 value to dest.
size_t dio_output_used(struct raw_data_out *dout)
Return the maximum number of bytes used.
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
Initializes the input to the given input buffer and the given number of valid input bytes.
bool dio_get_string_raw(struct data_in *din, char *dest, size_t max_dest_size)
Take string.
#define fc_assert_ret_val(condition, val)
#define log_debug(message,...)
const char * secfile_error()
Returns the last error which occurred in a string.
void secfile_destroy(struct section_file *secfile)
Free a section file.
struct section_file * secfile_from_stream(QIODevice *stream, bool allow_duplicates)
Create a section file from a stream.
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
Lookup a string value in the secfile.
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
Lookup a integer value in the secfile.
#define SERVER_LAN_VERSION
struct server_list * server_scan_get_list(struct server_scan *scan)
Returns the srv_list currently held by the scan (may be nullptr).
static void delete_server_list(struct server_list *server_list)
Frees everything associated with a server list including the server list itself (so the server_list i...
static bool begin_metaserver_scan(struct server_scan *scan)
Begin a metaserver scan for servers.
static bool meta_read_response(struct server_scan *scan)
Read the reply string from the metaserver.
enum announce_type announce
static void metaserver_scan(void *arg)
Metaserver scan thread entry point.
struct server_scan * server_scan_begin(enum server_scan_type type, ServerScanErrorFunc error_func)
Creates a new server scan and returns it, or nullptr if impossible.
void server_scan_finish(struct server_scan *scan)
Closes the socket listening on the scan, frees the list of servers, and frees the memory allocated fo...
static struct server_list * parse_metaserver_data(QIODevice *f)
The server sends a stream in a registry 'ini' type format.
enum server_scan_type server_scan_get_type(const struct server_scan *scan)
A simple query function to determine the type of a server scan (previously allocated in server_scan_b...
enum server_scan_status server_scan_poll(struct server_scan *scan)
A function to query servers of the server scan.
#define server_list_iterate_end
#define server_list_iterate(serverlist, pserver)
void(* ServerScanErrorFunc)(struct server_scan *scan, const char *message)
char * get_multicast_group(bool ipv6_preferred)
Returns string which gives the multicast group IP address for finding servers on the LAN,...
ServerScanErrorFunc error_func
struct server_list * servers
enum server_scan_status status
enum server_scan_type type
struct server_scan::@143 meta
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
int fc_strcasecmp(const char *str0, const char *str1)
Compare strings like strcmp(), but ignoring case.
#define sz_strlcpy(dest, src)
const char * freeciv21_version()
Returns the raw version string.