Files
fs2open.github.com/code/network/valid.cpp
T
Taylor Richards 6a9b6a38e9 fix several uninitialized variable warnings (#7087)
Initialize structs as appropriate in PXO and mdns code that were reported by
gcc/clang/coverity.
2025-10-14 13:51:53 -04:00

835 lines
22 KiB
C++

/*
* Copyright (C) Volition, Inc. 2005. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
//Validate tracker user class
#ifndef _WIN32
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cerrno>
#include <netdb.h>
#endif
#ifdef SCP_BSD
#include <sys/socket.h>
#endif
#include "network/multi.h"
#include "network/ptrack.h"
#include "network/valid.h"
#include "network/psnet2.h"
#include "network/multi_fstracker.h"
#include "io/timer.h"
// check structs for size compatibility
SDL_COMPILE_TIME_ASSERT(vmt_validate_mission_req_struct, sizeof(vmt_validate_mission_req_struct) == 104);
// Variables
static udp_packet_header PacketHeader;
static validate_id_request *ValidIDReq;
static int ValidState;
static SOCKADDR_STORAGE rtrackaddr;
static int ValidFirstSent;
static int ValidLastSent;
static char *Psztracker_id;
// mission validation
int MissionValidState;
static int MissionValidFirstSent;
static int MissionValidLastSent;
// squad war validation
int SquadWarValidState;
static int SquadWarFirstSent;
static int SquadWarLastSent;
// data validation
int DataValidState;
static SCP_vector<uint32_t> DataValidStatus;
static int DataValidFirstSent;
static int DataValidLastSent;
// squad war response
static squad_war_response SquadWarValidateResponse;
static int SerializeValidatePacket(const udp_packet_header *uph, ubyte *data)
{
unsigned int packet_size = 0;
int i;
PXO_ADD_DATA(uph->type);
PXO_ADD_USHORT(uph->len);
PXO_ADD_UINT(uph->code);
PXO_ADD_USHORT(uph->xcode);
PXO_ADD_UINT(uph->sig);
PXO_ADD_UINT(uph->security);
switch (uph->type) {
// no extra data for this
case UNT_CONTROL:
break;
case UNT_LOGIN_AUTH_REQUEST: {
auto id_req = reinterpret_cast<const validate_id_request *>(&uph->data);
PXO_ADD_DATA(id_req->login);
PXO_ADD_DATA(id_req->password);
PXO_ADD_DATA(id_req->tracker_id); // junk here, just for size
break;
}
case UNT_VALID_MSN_REQ: {
auto mis_req = reinterpret_cast<const vmt_validate_mission_req_struct *>(&uph->data);
PXO_ADD_UINT(mis_req->checksum);
memcpy(data+packet_size, mis_req->file_name, strlen(mis_req->file_name));
packet_size += static_cast<unsigned int>(strlen(mis_req->file_name));
data[packet_size] = '\0';
packet_size++;
break;
}
case UNT_VALID_DATA_REQ: {
// as a dynamically sized packet this should have already been
// packed, so just copy the data over
const unsigned int dsize = uph->len - PACKED_HEADER_ONLY_SIZE;
memcpy(data+packet_size, uph->data, dsize);
packet_size += dsize;
break;
}
case UNT_VALID_SW_MSN_REQ: {
auto sw_req = reinterpret_cast<const squad_war_request *>(&uph->data);
for (i = 0; i < MAX_SQUAD_PLAYERS; i++) {
PXO_ADD_INT(sw_req->squad_plr1[i]);
}
for (i = 0; i < MAX_SQUAD_PLAYERS; i++) {
PXO_ADD_INT(sw_req->squad_plr2[i]);
}
PXO_ADD_DATA(sw_req->squad_count1);
PXO_ADD_DATA(sw_req->squad_count2);
PXO_ADD_DATA(sw_req->match_code);
PXO_ADD_DATA(sw_req->mission_filename);
PXO_ADD_INT(sw_req->mission_checksum);
break;
}
// we shouldn't be sending any other packet types
default:
Int3();
break;
}
Assert(packet_size >= PACKED_HEADER_ONLY_SIZE);
Assert(packet_size == uph->len);
Assert(packet_size <= MAX_PACKET_SIZE);
return static_cast<int>(packet_size);
}
static void DeserializeValidatePacket(const ubyte *data, const int data_size, udp_packet_header *uph)
{
int offset = 0;
memset(uph, 0, sizeof(udp_packet_header));
// make sure we received a complete base packet
if (data_size < static_cast<int>(PACKED_HEADER_ONLY_SIZE)) {
uph->len = 0;
uph->type = 0xff;
return;
}
PXO_GET_DATA(uph->type);
PXO_GET_USHORT(uph->len);
PXO_GET_UINT(uph->code);
PXO_GET_USHORT(uph->xcode);
PXO_GET_UINT(uph->sig);
PXO_GET_UINT(uph->security);
// sanity check data size to make sure we reveived all of the expected packet
// (the -1 is because psnet2 pops off one byte)
if (static_cast<int>(uph->len)-1 > data_size) {
uph->len = 0;
uph->type = 0xff;
return;
}
switch (uph->type) {
// no extra data for these
case UNT_CONTROL:
case UNT_CONTROL_VALIDATION:
case UNT_LOGIN_NO_AUTH:
case UNT_VALID_MSN_RSP:
break;
case UNT_VALID_TBL_RSP: {
short game_id;
PXO_GET_SHORT(game_id);
memcpy(uph->data, &game_id, sizeof(short));
SDL_strlcpy(reinterpret_cast<char *>(uph->data+sizeof(short)), reinterpret_cast<const char *>(data+offset), SDL_arraysize(uph->data) - sizeof(short));
break;
}
case UNT_VALID_DATA_RSP: {
// as a dynamically sized packet we can't really handle it here
// that easily so just copy the data over for later use
const unsigned int dsize = uph->len - PACKED_HEADER_ONLY_SIZE;
memcpy(uph->data, data+offset, dsize);
offset += dsize;
break;
}
case UNT_LOGIN_AUTHENTICATED: {
SDL_strlcpy(reinterpret_cast<char *>(uph->data), reinterpret_cast<const char *>(data+offset), SDL_arraysize(uph->data));
break;
}
case UNT_VALID_SW_MSN_RSP: {
auto sw_resp = reinterpret_cast<squad_war_response *>(&uph->data);
PXO_GET_DATA(sw_resp->reason);
PXO_GET_DATA(sw_resp->accepted);
break;
}
default:
break;
}
//Assert(offset == data_size);
}
int InitValidateClient()
{
ValidFirstSent = 0;
ValidLastSent = 0;
ValidState = VALID_STATE_IDLE;
MissionValidFirstSent = 0;
MissionValidLastSent = 0;
MissionValidState = VALID_STATE_IDLE;
SquadWarFirstSent = 0;
SquadWarLastSent = 0;
SquadWarValidState = VALID_STATE_IDLE;
DataValidFirstSent = 0;
DataValidLastSent = 0;
DataValidState = VALID_STATE_IDLE;
psnet_get_addr(Multi_options_g.user_tracker_ip, REGPORT, &rtrackaddr);
return 1;
}
//Call with a valid struct to validate a user
//Call with NULL to poll
//Return codes:
// -3 Still waiting (returned if we were waiting for a tracker response and ValidateUser was called with a non-NULL value
// -2 Timeout waiting for tracker to respond
// -1 User invalid
// 0 Still waiting for response from tracker/Idle
// 1 User valid
int ValidateUser(validate_id_request *valid_id, char *trackerid)
{
ubyte packet_data[sizeof(udp_packet_header)];
int packet_length = 0;
ValidIdle();
if(valid_id==nullptr)
{
switch(ValidState)
{
case VALID_STATE_IDLE:
return 0;
case VALID_STATE_WAITING:
return 0;
case VALID_STATE_VALID:
ValidState = VALID_STATE_IDLE;
return 1;
case VALID_STATE_INVALID:
ValidState = VALID_STATE_IDLE;
return -1;
case VALID_STATE_TIMEOUT:
ValidState = VALID_STATE_IDLE;
return -2;
}
return 0;
}
else
{
if(ValidState==VALID_STATE_IDLE)
{
//First, flush the input buffer for the socket
fd_set read_fds;
struct timeval timeout;
timeout.tv_sec=0;
timeout.tv_usec=0;
FD_ZERO(&read_fds); // NOLINT
FD_SET(Psnet_socket, &read_fds);
while(SELECT(static_cast<int>(Psnet_socket+1),&read_fds,nullptr,nullptr,&timeout, PSNET_TYPE_VALIDATION))
{
int addrsize;
SOCKADDR_STORAGE fromaddr;
udp_packet_header inpacket;
addrsize = sizeof(fromaddr);
RECVFROM(Psnet_socket, reinterpret_cast<char *>(&inpacket), sizeof(udp_packet_header), 0,
reinterpret_cast<LPSOCKADDR>(&fromaddr), &addrsize, PSNET_TYPE_VALIDATION);
}
Psztracker_id = trackerid;
//Build the request packet
SDL_zero(PacketHeader);
PacketHeader.type = UNT_LOGIN_AUTH_REQUEST;
PacketHeader.xcode = static_cast<unsigned short>(Multi_fs_tracker_game_id);
PacketHeader.len = PACKED_HEADER_ONLY_SIZE+sizeof(validate_id_request);
ValidIDReq = reinterpret_cast<validate_id_request *>(&PacketHeader.data);
SDL_strlcpy(ValidIDReq->login, valid_id->login, SDL_arraysize(ValidIDReq->login));
SDL_strlcpy(ValidIDReq->password, valid_id->password, SDL_arraysize(ValidIDReq->password));
packet_length = SerializeValidatePacket(&PacketHeader, packet_data);
SENDTO(Psnet_socket, reinterpret_cast<char *>(&packet_data), packet_length, 0, reinterpret_cast<LPSOCKADDR>(&rtrackaddr), sizeof(rtrackaddr), PSNET_TYPE_VALIDATION);
ValidState = VALID_STATE_WAITING;
ValidFirstSent = timer_get_milliseconds();
ValidLastSent = timer_get_milliseconds();
return 0;
}
else
{
return -3;
}
}
}
void ValidIdle()
{
fd_set read_fds;
struct timeval timeout;
ubyte packet_data[sizeof(udp_packet_header)];
int packet_length = 0;
PSNET_TOP_LAYER_PROCESS();
timeout.tv_sec=0;
timeout.tv_usec=0;
FD_ZERO(&read_fds); // NOLINT
FD_SET(Psnet_socket, &read_fds);
if(SELECT(static_cast<int>(Psnet_socket+1),&read_fds,nullptr,nullptr,&timeout, PSNET_TYPE_VALIDATION)){
int bytesin;
int addrsize;
SOCKADDR_STORAGE fromaddr;
udp_packet_header inpacket;
SDL_zero(inpacket);
addrsize = sizeof(fromaddr);
bytesin = RECVFROM(Psnet_socket, reinterpret_cast<char *>(&packet_data), sizeof(udp_packet_header), 0,
reinterpret_cast<LPSOCKADDR>(&fromaddr), &addrsize, PSNET_TYPE_VALIDATION);
if (bytesin > 0) {
DeserializeValidatePacket(packet_data, bytesin, &inpacket);
// decrease packet size by 1
inpacket.len--;
#ifndef NDEBUG
} else {
int wserr=WSAGetLastError();
mprintf(("recvfrom() failure. WSAGetLastError() returned %d\n",wserr));
#endif
}
FD_ZERO(&read_fds); // NOLINT
FD_SET(Psnet_socket, &read_fds);
//Check to make sure the packets ok
if ( (bytesin > 0) && (bytesin == inpacket.len) ) {
const ubyte *data = inpacket.data;
unsigned int offset = 0;
switch(inpacket.type)
{
case UNT_LOGIN_NO_AUTH:
if(ValidState == VALID_STATE_WAITING)
{
ValidState = VALID_STATE_INVALID;
}
break;
case UNT_LOGIN_AUTHENTICATED:
if(ValidState == VALID_STATE_WAITING)
{
ValidState = VALID_STATE_VALID;
SDL_strlcpy(Psztracker_id, reinterpret_cast<const char *>(&inpacket.data), TRACKER_ID_LEN);
}
break;
// fs2 mission validation response
case UNT_VALID_MSN_RSP:
if(MissionValidState == VALID_STATE_WAITING){
if(inpacket.code==2){
MissionValidState = VALID_STATE_VALID;
} else {
MissionValidState = VALID_STATE_INVALID;
}
}
break;
// fs2 squad war validation response
case UNT_VALID_SW_MSN_RSP:
if(SquadWarValidState == VALID_STATE_WAITING){
// copy the data
Assert((static_cast<size_t>(bytesin) - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response));
if((static_cast<size_t>(bytesin) - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response)){
memset(&SquadWarValidateResponse, 0, sizeof(squad_war_response));
memcpy(&SquadWarValidateResponse, inpacket.data, sizeof(squad_war_response));
// now check to see if we're good
if(SquadWarValidateResponse.accepted){
SquadWarValidState = VALID_STATE_VALID;
} else {
SquadWarValidState = VALID_STATE_INVALID;
}
} else {
SquadWarValidState = VALID_STATE_INVALID;
}
}
break;
// data validation response
case UNT_VALID_DATA_RSP: {
if (DataValidState == VALID_STATE_WAITING) {
if (inpacket.code == 2) {
DataValidState = VALID_STATE_VALID;
} else {
DataValidState = VALID_STATE_INVALID;
}
DataValidStatus.clear();
// special error case
if (inpacket.code == 0) {
break;
}
uint8_t flags;
PXO_GET_DATA(flags);
if (flags & VDR_FLAG_IDENT) {
char text[100];
PXO_GET_SHORT(Multi_fs_tracker_game_id);
PXO_GET_STRING(text);
Multi_fs_tracker_game_tag = text;
PXO_GET_STRING(text);
Multi_fs_tracker_game_name = text;
}
if (flags & VDR_FLAG_STATUS) {
uint8_t status_count;
uint32_t status;
PXO_GET_DATA(status_count);
for (auto i = 0; i < status_count; ++i) {
PXO_GET_UINT(status);
DataValidStatus.push_back(status);
}
}
}
break;
}
case UNT_CONTROL_VALIDATION:
Int3();
break;
case UNT_CONTROL:
Int3();
break;
}
AckValidServer(inpacket.sig);
}
}
if(ValidState == VALID_STATE_WAITING)
{
if((timer_get_milliseconds()-ValidFirstSent)>=PILOT_REQ_TIMEOUT)
{
ValidState = VALID_STATE_TIMEOUT;
}
else if((timer_get_milliseconds()-ValidLastSent)>=PILOT_REQ_RESEND_TIME)
{
//Send 'da packet
packet_length = SerializeValidatePacket(&PacketHeader, packet_data);
SENDTO(Psnet_socket, reinterpret_cast<char *>(&packet_data), packet_length, 0, reinterpret_cast<LPSOCKADDR>(&rtrackaddr), sizeof(rtrackaddr), PSNET_TYPE_VALIDATION);
ValidLastSent = timer_get_milliseconds();
}
}
if(MissionValidState == VALID_STATE_WAITING)
{
if((timer_get_milliseconds()-MissionValidFirstSent)>=PILOT_REQ_TIMEOUT)
{
MissionValidState = VALID_STATE_TIMEOUT;
}
}
if(SquadWarValidState == VALID_STATE_WAITING)
{
if((timer_get_milliseconds()-SquadWarFirstSent)>=PILOT_REQ_TIMEOUT)
{
SquadWarValidState = VALID_STATE_TIMEOUT;
}
}
if (DataValidState == VALID_STATE_WAITING) {
if ( (timer_get_milliseconds() - DataValidFirstSent) >= PILOT_REQ_TIMEOUT ) {
DataValidState = VALID_STATE_TIMEOUT;
}
}
}
//Send an ACK to the server
void AckValidServer(unsigned int sig)
{
udp_packet_header ack_pack{};
ubyte packet_data[sizeof(udp_packet_header)];
int packet_length = 0;
ack_pack.type = UNT_CONTROL;
ack_pack.sig = sig;
ack_pack.code = CMD_CLIENT_RECEIVED;
ack_pack.len = PACKED_HEADER_ONLY_SIZE;
packet_length = SerializeValidatePacket(&ack_pack, packet_data);
Assert(packet_length == PACKED_HEADER_ONLY_SIZE);
SENDTO(Psnet_socket, reinterpret_cast<char *>(&packet_data), packet_length, 0, reinterpret_cast<LPSOCKADDR>(&rtrackaddr), sizeof(rtrackaddr), PSNET_TYPE_VALIDATION);
}
// call with a valid struct to validate a mission
// call with NULL to poll
// Return codes:
// -3 Still waiting (returned if we were waiting for a tracker response and ValidateMission was called with a non-NULL value
// -2 Timeout waiting for tracker to respond
// -1 User invalid
// 0 Still waiting for response from tracker/Idle
// 1 User valid
int ValidateMission(vmt_validate_mission_req_struct *valid_msn)
{
ubyte packet_data[sizeof(udp_packet_header)];
int packet_length = 0;
ValidIdle();
if(valid_msn==nullptr)
{
switch(MissionValidState)
{
case VALID_STATE_IDLE:
return 0;
case VALID_STATE_WAITING:
return 0;
case VALID_STATE_VALID:
MissionValidState = VALID_STATE_IDLE;
return 1;
case VALID_STATE_INVALID:
MissionValidState = VALID_STATE_IDLE;
return -1;
case VALID_STATE_TIMEOUT:
MissionValidState = VALID_STATE_IDLE;
return -2;
}
return 0;
}
else
{
if(MissionValidState==VALID_STATE_IDLE)
{
//First, flush the input buffer for the socket
fd_set read_fds;
struct timeval timeout;
timeout.tv_sec=0;
timeout.tv_usec=0;
while(SELECT(static_cast<int>(Psnet_socket+1),&read_fds,nullptr,nullptr,&timeout, PSNET_TYPE_VALIDATION))
{
int addrsize;
SOCKADDR_STORAGE fromaddr;
udp_packet_header inpacket;
FD_ZERO(&read_fds); // NOLINT
FD_SET(Psnet_socket, &read_fds);
addrsize = sizeof(fromaddr);
RECVFROM(Psnet_socket, reinterpret_cast<char *>(&inpacket), sizeof(udp_packet_header), 0,
reinterpret_cast<LPSOCKADDR>(&fromaddr), &addrsize, PSNET_TYPE_VALIDATION);
}
//only send the header, the checksum and the string length plus the null
SDL_zero(PacketHeader);
PacketHeader.type = UNT_VALID_MSN_REQ;
PacketHeader.xcode = static_cast<unsigned short>(Multi_fs_tracker_game_id);
PacketHeader.len = static_cast<unsigned short>(PACKED_HEADER_ONLY_SIZE + sizeof(int)+1+strlen(valid_msn->file_name));
memcpy(PacketHeader.data,valid_msn,PacketHeader.len-PACKED_HEADER_ONLY_SIZE);
packet_length = SerializeValidatePacket(&PacketHeader, packet_data);
SENDTO(Psnet_socket, reinterpret_cast<char *>(&packet_data), packet_length, 0, reinterpret_cast<LPSOCKADDR>(&rtrackaddr), sizeof(rtrackaddr), PSNET_TYPE_VALIDATION);
MissionValidState = VALID_STATE_WAITING;
MissionValidFirstSent = timer_get_milliseconds();
MissionValidLastSent = timer_get_milliseconds();
return 0;
}
else
{
return -3;
}
}
}
// query the usertracker to validate a squad war match
// call with a valid struct to validate a mission
// call with NULL to poll
// Return codes:
// -3 Still waiting (returned if we were waiting for a tracker response and ValidateSquadWae was called with a non-NULL value
// -2 Timeout waiting for tracker to respond
// -1 match invalid
// 0 Still waiting for response from tracker/Idle
// 1 match valid
int ValidateSquadWar(squad_war_request *sw_req, squad_war_response *sw_resp)
{
ubyte packet_data[sizeof(udp_packet_header)];
int packet_length = 0;
ValidIdle();
if(sw_req==nullptr){
switch(SquadWarValidState){
case VALID_STATE_IDLE:
return 0;
case VALID_STATE_WAITING:
return 0;
// fill in the response
case VALID_STATE_VALID:
SquadWarValidState = VALID_STATE_IDLE;
if(sw_resp != nullptr){
memcpy(sw_resp, &SquadWarValidateResponse, sizeof(squad_war_response));
}
return 1;
// fill in the response
case VALID_STATE_INVALID:
SquadWarValidState = VALID_STATE_IDLE;
if(sw_resp != nullptr){
memcpy(sw_resp, &SquadWarValidateResponse, sizeof(squad_war_response));
}
return -1;
case VALID_STATE_TIMEOUT:
SquadWarValidState = VALID_STATE_IDLE;
return -2;
}
return 0;
} else {
if(SquadWarValidState==VALID_STATE_IDLE){
// First, flush the input buffer for the socket
fd_set read_fds;
struct timeval timeout;
timeout.tv_sec=0;
timeout.tv_usec=0;
while(SELECT(static_cast<int>(Psnet_socket+1),&read_fds,nullptr,nullptr,&timeout, PSNET_TYPE_VALIDATION)){
int addrsize;
SOCKADDR_STORAGE fromaddr;
udp_packet_header inpacket;
FD_ZERO(&read_fds); // NOLINT
FD_SET(Psnet_socket, &read_fds);
addrsize = sizeof(fromaddr);
RECVFROM(Psnet_socket, reinterpret_cast<char *>(&inpacket), sizeof(udp_packet_header), 0,
reinterpret_cast<LPSOCKADDR>(&fromaddr), &addrsize, PSNET_TYPE_VALIDATION);
}
// only send the header, the checksum and the string length plus the null
SDL_zero(PacketHeader);
PacketHeader.type = UNT_VALID_SW_MSN_REQ;
PacketHeader.xcode = static_cast<unsigned short>(Multi_fs_tracker_game_id);
PacketHeader.len = static_cast<unsigned short>(PACKED_HEADER_ONLY_SIZE + sizeof(squad_war_request));
memcpy(PacketHeader.data, sw_req, PacketHeader.len-PACKED_HEADER_ONLY_SIZE);
packet_length = SerializeValidatePacket(&PacketHeader, packet_data);
SENDTO(Psnet_socket, reinterpret_cast<char *>(&packet_data), packet_length, 0, reinterpret_cast<LPSOCKADDR>(&rtrackaddr), sizeof(rtrackaddr), PSNET_TYPE_VALIDATION);
SquadWarValidState = VALID_STATE_WAITING;
SquadWarFirstSent = timer_get_milliseconds();
SquadWarLastSent = timer_get_milliseconds();
return 0;
} else {
return -3;
}
}
}
// custom packer for valid data packet since we can't easily serialize it through
// the normal function
static unsigned short PackValidDataRequest(const vmt_valid_data_req_struct *vreq, ubyte *data)
{
unsigned short packet_size = 0;
PXO_ADD_DATA(vreq->type);
PXO_ADD_DATA(vreq->flags);
PXO_ADD_DATA(vreq->num_files);
for (auto &file : vreq->files) {
Assert(packet_size+sizeof(uint32_t)+file.name.length()+1 < MAX_UDP_DATA_LENGH);
PXO_ADD_UINT(file.crc);
PXO_ADD_STRING(file.name.c_str(), MAX_UDP_DATA_LENGH);
}
return packet_size;
}
// call with a valid struct to validate a table
// call with NULL to poll
// Return codes:
// -3 Still waiting (returned if we were waiting for a tracker response and ValidateTable was called with a non-NULL value
// -2 Timeout waiting for tracker to respond
// -1 table invalid
// 0 Still waiting for response from tracker/Idle
// 1 table valid
int ValidateData(const vmt_valid_data_req_struct *vreq)
{
ubyte packet_data[sizeof(udp_packet_header)];
int packet_length = 0;
ValidIdle();
if (vreq == nullptr) {
switch (DataValidState) {
case VALID_STATE_IDLE:
return 0;
case VALID_STATE_WAITING:
return 0;
case VALID_STATE_VALID:
DataValidState = VALID_STATE_IDLE;
return 1;
case VALID_STATE_INVALID:
DataValidState = VALID_STATE_IDLE;
return -1;
case VALID_STATE_TIMEOUT:
DataValidState = VALID_STATE_IDLE;
return -2;
}
return 0;
} else {
if (DataValidState == VALID_STATE_IDLE) {
fd_set read_fds;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
while ( SELECT(static_cast<int>(Psnet_socket+1), &read_fds, nullptr, nullptr, &timeout, PSNET_TYPE_VALIDATION) ) {
int addrsize;
SOCKADDR_STORAGE fromaddr;
udp_packet_header inpacket;
FD_ZERO(&read_fds); // NOLINT
FD_SET(Psnet_socket, &read_fds);
addrsize = sizeof(fromaddr);
RECVFROM(Psnet_socket, reinterpret_cast<char *>(&inpacket), sizeof(udp_packet_header), 0,
reinterpret_cast<LPSOCKADDR>(&fromaddr), &addrsize, PSNET_TYPE_VALIDATION);
}
SDL_zero(PacketHeader);
PacketHeader.type = UNT_VALID_DATA_REQ;
PacketHeader.xcode = static_cast<unsigned short>(Multi_fs_tracker_game_id);
PacketHeader.len = PackValidDataRequest(vreq, PacketHeader.data) + PACKED_HEADER_ONLY_SIZE;
packet_length = SerializeValidatePacket(&PacketHeader, packet_data);
SENDTO(Psnet_socket, reinterpret_cast<char *>(&packet_data), packet_length, 0,reinterpret_cast<LPSOCKADDR>(&rtrackaddr), sizeof(rtrackaddr), PSNET_TYPE_VALIDATION);
DataValidState = VALID_STATE_WAITING;
DataValidStatus.clear();
DataValidFirstSent = timer_get_milliseconds();
DataValidLastSent = timer_get_milliseconds();
return 0;
} else {
return -1;
}
}
}
// if VDR_FLAG_STATUS was set then this should return the valid status of the
// file at 'idx' in the packet
bool IsDataIndexValid(const unsigned int idx)
{
unsigned int count = idx / 32;
unsigned int index = idx % 32;
if (DataValidStatus.empty() || count > DataValidStatus.size()) {
return false;
}
return (DataValidStatus[count] & 1<<index);
}