mirror of
https://github.com/rocketsciencegg/qstat
synced 2026-08-18 12:23:04 -04:00
Fix Hexen 2 player details by enabling next_player_info flow. Also: * Extract code send code into send_packet_raw and use in all send methods. This enables easy conversion of callers using send(...) to use a version which supports packet debugging. Fixes #114
146 lines
3.1 KiB
C
146 lines
3.1 KiB
C
/*
|
|
* qstat
|
|
* by Steve Jankowski
|
|
*
|
|
* qserver functions
|
|
* Copyright 2004 Ludwig Nussel
|
|
*
|
|
* Licensed under the Artistic License, see LICENSE.txt for license terms
|
|
*/
|
|
|
|
#include "qstat.h"
|
|
#include "qserver.h"
|
|
#include "debug.h"
|
|
|
|
#ifndef _WIN32
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
|
|
// TODO: get rid of this and use send_packet instead, remove n_requests hack from a2s
|
|
query_status_t
|
|
qserver_send_initial(struct qserver *server, const char *data, size_t len)
|
|
{
|
|
query_status_t status;
|
|
|
|
status = send_packet_raw(server, data, len);
|
|
|
|
if ((server->retry1 == n_retries) || server->flags & FLAG_BROADCAST) {
|
|
gettimeofday(&server->packet_time1, NULL);
|
|
} else {
|
|
server->n_retries++;
|
|
}
|
|
|
|
server->retry1--;
|
|
server->n_packets++;
|
|
|
|
return (status);
|
|
}
|
|
|
|
query_status_t
|
|
qserver_send(struct qserver *server, const char *data, size_t len)
|
|
{
|
|
query_status_t status;
|
|
|
|
status = send_packet_raw(server, data, len);
|
|
|
|
server->retry1 = n_retries - 1;
|
|
gettimeofday(&server->packet_time1, NULL);
|
|
server->n_requests++;
|
|
server->n_packets++;
|
|
|
|
return (status);
|
|
}
|
|
|
|
int
|
|
send_broadcast(struct qserver *server, const char *pkt, size_t pktlen)
|
|
{
|
|
struct sockaddr_in addr;
|
|
|
|
addr.sin_family = AF_INET;
|
|
if (no_port_offset || server->flags & TF_NO_PORT_OFFSET) {
|
|
addr.sin_port = htons(server->port);
|
|
} else {
|
|
addr.sin_port = htons((unsigned short)(server->port + server->type->port_offset));
|
|
}
|
|
addr.sin_addr.s_addr = server->ipaddr;
|
|
memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero));
|
|
|
|
return (sendto(server->fd, (const char *)pkt, pktlen, 0, (struct sockaddr *)&addr, sizeof(addr)));
|
|
}
|
|
|
|
int
|
|
register_send(struct qserver *server)
|
|
{
|
|
if ((server->retry1 == n_retries) || server->flags & FLAG_BROADCAST) {
|
|
server->n_requests++;
|
|
} else {
|
|
server->n_retries++;
|
|
}
|
|
|
|
// New request so reset the sent time. This ensures
|
|
// that we record an accurate ping time even on retry
|
|
gettimeofday(&server->packet_time1, NULL);
|
|
server->retry1--;
|
|
server->n_packets++;
|
|
|
|
return (INPROGRESS);
|
|
}
|
|
|
|
query_status_t
|
|
send_packet_raw(struct qserver *server, const char *data, size_t len)
|
|
{
|
|
debug(2, "[%s] send", server->type->type_prefix);
|
|
if (4 <= get_debug_level()) {
|
|
output_packet(server, data, len, 1);
|
|
}
|
|
|
|
if (data) {
|
|
int ret;
|
|
if (server->flags & FLAG_BROADCAST) {
|
|
ret = send_broadcast(server, data, len);
|
|
} else {
|
|
ret = send(server->fd, data, len, 0);
|
|
}
|
|
|
|
if (ret == SOCKET_ERROR) {
|
|
return (send_error(server, ret));
|
|
}
|
|
}
|
|
|
|
return (INPROGRESS);
|
|
}
|
|
|
|
query_status_t
|
|
send_packet(struct qserver *server, const char *data, size_t len)
|
|
{
|
|
query_status_t rc;
|
|
|
|
rc = send_packet_raw(server, data, len);
|
|
if (rc == SYS_ERROR) {
|
|
return (rc);
|
|
}
|
|
|
|
return (register_send(server));
|
|
}
|
|
|
|
query_status_t
|
|
send_error(struct qserver *server, int rc)
|
|
{
|
|
unsigned int ipaddr = ntohl(server->ipaddr);
|
|
const char *errstr = strerror(errno);
|
|
|
|
fprintf(stderr, "Error on %d.%d.%d.%d: %s, skipping ...\n",
|
|
(ipaddr >> 24) & 0xff,
|
|
(ipaddr >> 16) & 0xff,
|
|
(ipaddr >> 8) & 0xff,
|
|
ipaddr & 0xff,
|
|
errstr
|
|
);
|
|
return (SYS_ERROR);
|
|
}
|