mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
The socket is a value to be assigned, not an index to be used. As such there is no safety check to be done here and doing so just breaks things. Fixes networking on Windows.
744 lines
19 KiB
C++
744 lines
19 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.
|
|
*
|
|
*/
|
|
|
|
//Pilot tracker client code
|
|
|
|
#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 "globalincs/pstypes.h"
|
|
#include "io/timer.h"
|
|
#include "network/multi.h"
|
|
#include "network/ptrack.h"
|
|
#include "network/psnet2.h"
|
|
#include "network/multi_fstracker.h"
|
|
|
|
|
|
// check structs for size compatibility
|
|
SDL_COMPILE_TIME_ASSERT(udp_packet_header, sizeof(udp_packet_header) == 517);
|
|
SDL_COMPILE_TIME_ASSERT(vmt_fs2open_struct, sizeof(vmt_fs2open_struct) == 480);
|
|
SDL_COMPILE_TIME_ASSERT(validate_id_request, sizeof(validate_id_request) == 60);
|
|
SDL_COMPILE_TIME_ASSERT(squad_war_request, sizeof(squad_war_request) == 104);
|
|
SDL_COMPILE_TIME_ASSERT(squad_war_response, sizeof(squad_war_response) == 256);
|
|
SDL_COMPILE_TIME_ASSERT(squad_war_result, sizeof(squad_war_result) == 72);
|
|
SDL_COMPILE_TIME_ASSERT(pilot_request, sizeof(pilot_request) == 32);
|
|
|
|
|
|
//Variables
|
|
|
|
static SOCKADDR_STORAGE ptrackaddr;
|
|
|
|
|
|
static int FSWriteState;
|
|
static int FSReadState;
|
|
static unsigned int FSLastSentWrite;
|
|
static unsigned int FSFirstSentWrite;
|
|
static unsigned int FSLastSent;
|
|
static unsigned int FSFirstSent;
|
|
|
|
static int SWWriteState;
|
|
static unsigned int SWLastSentWrite;
|
|
static unsigned int SWFirstSentWrite;
|
|
|
|
|
|
static udp_packet_header fs_pilot_req, fs_pilot_write, sw_res_write;
|
|
static pilot_request *fs_pr;
|
|
static vmt_stats_struct *ReadFSPilot;
|
|
|
|
// squad war response
|
|
static squad_war_response SquadWarWriteResponse;
|
|
|
|
|
|
static int SerializePilotPacket(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_PILOT_DATA_WRITE_NEW: {
|
|
auto fsos = reinterpret_cast<const vmt_stats_struct *>(&uph->data);
|
|
|
|
PXO_ADD_INT(fsos->tracker_id);
|
|
PXO_ADD_DATA(fsos->pilot_name);
|
|
|
|
PXO_ADD_INT(fsos->score);
|
|
PXO_ADD_INT(fsos->rank);
|
|
PXO_ADD_INT(fsos->assists);
|
|
PXO_ADD_INT(fsos->kill_count);
|
|
PXO_ADD_INT(fsos->kill_count_ok);
|
|
PXO_ADD_UINT(fsos->p_shots_fired);
|
|
PXO_ADD_UINT(fsos->s_shots_fired);
|
|
|
|
PXO_ADD_UINT(fsos->p_shots_hit);
|
|
PXO_ADD_UINT(fsos->s_shots_hit);
|
|
|
|
PXO_ADD_UINT(fsos->p_bonehead_hits);
|
|
PXO_ADD_UINT(fsos->s_bonehead_hits);
|
|
PXO_ADD_INT(fsos->bonehead_kills);
|
|
|
|
PXO_ADD_UINT(fsos->missions_flown);
|
|
PXO_ADD_UINT(fsos->flight_time);
|
|
PXO_ADD_UINT(fsos->last_flown);
|
|
|
|
PXO_ADD_INT(fsos->security);
|
|
PXO_ADD_UINT(fsos->checksum);
|
|
|
|
PXO_ADD_DATA(fsos->virgin_pilot);
|
|
|
|
// skip 1-byte pad
|
|
|
|
PXO_ADD_DATA(fsos->num_medals);
|
|
PXO_ADD_DATA(fsos->num_ships);
|
|
|
|
const int count = std::min(static_cast<unsigned short>(fsos->num_medals + fsos->num_ships), MAX_FS2OPEN_COUNTS);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
PXO_ADD_USHORT(fsos->counts[i]);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case UNT_SW_RESULT_WRITE: {
|
|
auto sw_result = reinterpret_cast<const squad_war_result *>(&uph->data);
|
|
|
|
PXO_ADD_DATA(sw_result->match_code);
|
|
PXO_ADD_DATA(sw_result->result);
|
|
PXO_ADD_DATA(sw_result->squad_count1);
|
|
PXO_ADD_DATA(sw_result->squad_count2);
|
|
PXO_ADD_DATA(sw_result->pad); // junk, for size/alignment
|
|
|
|
for (i = 0; i < MAX_SQUAD_PLAYERS; i++) {
|
|
PXO_ADD_INT(sw_result->squad_winners[i]);
|
|
}
|
|
|
|
for (i = 0; i < MAX_SQUAD_PLAYERS; i++) {
|
|
PXO_ADD_INT(sw_result->squad_losers[i]);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case UNT_PILOT_DATA_READ_NEW:
|
|
case UNT_PILOT_DATA_READ: {
|
|
auto pr = reinterpret_cast<const pilot_request *>(&uph->data);
|
|
|
|
PXO_ADD_DATA(pr->pilot_name);
|
|
PXO_ADD_DATA(pr->tracker_id);
|
|
PXO_ADD_DATA(pr->pad); // junk, for size/alignment
|
|
|
|
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 DeserializePilotPacket(const ubyte *data, const int data_size, udp_packet_header *uph)
|
|
{
|
|
int offset = 0;
|
|
int i;
|
|
|
|
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_PILOT_READ_FAILED:
|
|
case UNT_PILOT_WRITE_SUCCESS:
|
|
case UNT_PILOT_WRITE_FAILED:
|
|
break;
|
|
|
|
case UNT_PILOT_DATA_RESPONSE: {
|
|
auto fsos = reinterpret_cast<vmt_stats_struct *>(&uph->data);
|
|
|
|
PXO_GET_INT(fsos->tracker_id);
|
|
PXO_GET_DATA(fsos->pilot_name);
|
|
|
|
PXO_GET_INT(fsos->score);
|
|
PXO_GET_INT(fsos->rank);
|
|
PXO_GET_INT(fsos->assists);
|
|
PXO_GET_INT(fsos->kill_count);
|
|
PXO_GET_INT(fsos->kill_count_ok);
|
|
PXO_GET_UINT(fsos->p_shots_fired);
|
|
PXO_GET_UINT(fsos->s_shots_fired);
|
|
|
|
PXO_GET_UINT(fsos->p_shots_hit);
|
|
PXO_GET_UINT(fsos->s_shots_hit);
|
|
|
|
PXO_GET_UINT(fsos->p_bonehead_hits);
|
|
PXO_GET_UINT(fsos->s_bonehead_hits);
|
|
PXO_GET_INT(fsos->bonehead_kills);
|
|
|
|
PXO_GET_UINT(fsos->missions_flown);
|
|
PXO_GET_UINT(fsos->flight_time);
|
|
PXO_GET_UINT(fsos->last_flown);
|
|
|
|
PXO_GET_INT(fsos->security);
|
|
PXO_GET_UINT(fsos->checksum);
|
|
|
|
PXO_GET_DATA(fsos->virgin_pilot);
|
|
|
|
// skip 1-byte pad
|
|
|
|
PXO_GET_DATA(fsos->num_medals);
|
|
PXO_GET_DATA(fsos->num_ships);
|
|
|
|
const int count = std::min(static_cast<unsigned short>(fsos->num_medals + fsos->num_ships), MAX_FS2OPEN_COUNTS);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
PXO_GET_USHORT(fsos->counts[i]);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case UNT_SW_RESULT_RESPONSE: {
|
|
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 InitPilotTrackerClient()
|
|
{
|
|
FSWriteState = STATE_IDLE;
|
|
FSReadState = STATE_IDLE;
|
|
SWWriteState = STATE_IDLE;
|
|
|
|
ReadFSPilot = nullptr;
|
|
|
|
fs_pr = reinterpret_cast<pilot_request *>(&fs_pilot_req.data);
|
|
|
|
psnet_get_addr(Multi_options_g.user_tracker_ip, REGPORT, &ptrackaddr);
|
|
|
|
return 1;
|
|
}
|
|
|
|
// Returns:
|
|
// -3 Error -- Called with NULL, but no request is waiting
|
|
// -2 Error -- Already sending data (hasn't timed out yet)
|
|
// -1 Timeout trying to send pilot data
|
|
// 0 Sending
|
|
// 1 Data succesfully sent
|
|
// 2 Send Cancelled (data may still have been written already, we just haven't been ACK'd yet)
|
|
// 3 Pilot not written (for some reason)
|
|
|
|
// Call with NULL to poll
|
|
// Call with -1 to cancel send
|
|
// Call with valid pointer to a vmt_descent3_struct to initiate send
|
|
int SendFSPilotData(vmt_stats_struct *fs_pilot)
|
|
{
|
|
//First check the network
|
|
PollPTrackNet();
|
|
|
|
if(fs_pilot == nullptr)
|
|
{
|
|
if(FSWriteState == STATE_IDLE)
|
|
{
|
|
return -3;
|
|
}
|
|
if(FSWriteState == STATE_SENDING_PILOT)
|
|
{
|
|
return 0;
|
|
}
|
|
if(FSWriteState == STATE_WROTE_PILOT)
|
|
{
|
|
//We wrote this pilot, and now we are about to inform the app, so back to idle
|
|
FSWriteState = STATE_IDLE;
|
|
return 1;
|
|
}
|
|
if(FSWriteState == STATE_TIMED_OUT)
|
|
{
|
|
//We gave up on sending this pilot, and now we are about to inform the app, so back to idle
|
|
FSWriteState = STATE_IDLE;
|
|
|
|
return -1;
|
|
}
|
|
if(FSWriteState == STATE_WRITE_PILOT_FAILED)
|
|
{
|
|
//The tracker said this dude couldn't be written
|
|
FSWriteState = STATE_IDLE;
|
|
|
|
return 3;
|
|
}
|
|
|
|
}
|
|
else if(fs_pilot == reinterpret_cast<vmt_stats_struct *>(static_cast<uintptr_t>(0xffffffff)))
|
|
{
|
|
if(FSWriteState == STATE_IDLE)
|
|
{
|
|
return -3;
|
|
}
|
|
else
|
|
{
|
|
//Cancel this baby
|
|
FSWriteState = STATE_IDLE;
|
|
|
|
return 2;
|
|
}
|
|
|
|
}
|
|
else if(FSWriteState == STATE_IDLE)
|
|
{
|
|
//New request, send out the req, and go for it.
|
|
|
|
FSWriteState = STATE_SENDING_PILOT;
|
|
|
|
FSLastSentWrite = 0;
|
|
FSFirstSentWrite = timer_get_milliseconds();
|
|
|
|
// deal with variable length of vmt_fs2open_struct
|
|
const unsigned short size_offset = (MAX_FS2OPEN_COUNTS - (fs_pilot->num_ships + fs_pilot->num_medals)) * sizeof(unsigned short);
|
|
|
|
fs_pilot_write.type = UNT_PILOT_DATA_WRITE_NEW;
|
|
fs_pilot_write.code = CMD_GAME_FS2OPEN;
|
|
fs_pilot_write.xcode = static_cast<unsigned short>(Multi_fs_tracker_game_id);
|
|
fs_pilot_write.len = PACKED_HEADER_ONLY_SIZE+STATS_BLOCK_SIZE-size_offset;
|
|
memcpy(&fs_pilot_write.data,fs_pilot,sizeof(vmt_stats_struct));
|
|
|
|
return 0;
|
|
}
|
|
return -2;
|
|
}
|
|
|
|
// Returns:
|
|
// -3 Error -- Called with NULL, but no request is waiting
|
|
// -2 Error -- Already sending data (hasn't timed out yet)
|
|
// -1 Timeout trying to send pilot data
|
|
// 0 Sending
|
|
// 1 Data succesfully sent
|
|
// 2 Send Cancelled (data may still have been written already, we just haven't been ACK'd yet)
|
|
// 3 Pilot not written (for some reason)
|
|
|
|
// Call with NULL to poll
|
|
// Call with -1 to cancel send
|
|
// Call with valid pointer to a vmt_descent3_struct to initiate send
|
|
int SendSWData(squad_war_result *sw_res, squad_war_response *sw_resp)
|
|
{
|
|
//First check the network
|
|
PollPTrackNet();
|
|
|
|
if(sw_res == nullptr){
|
|
if(SWWriteState == STATE_IDLE){
|
|
return -3;
|
|
}
|
|
if(SWWriteState == STATE_SENDING_PILOT){
|
|
return 0;
|
|
}
|
|
|
|
// fill in the response
|
|
if(SWWriteState == STATE_WROTE_PILOT){
|
|
// We wrote this pilot, and now we are about to inform the app, so back to idle
|
|
SWWriteState = STATE_IDLE;
|
|
|
|
if(sw_resp != nullptr){
|
|
memcpy(sw_resp, &SquadWarWriteResponse, sizeof(squad_war_response));
|
|
}
|
|
return 1;
|
|
}
|
|
// fill in the response
|
|
if(SWWriteState == STATE_WRITE_PILOT_FAILED){
|
|
// The tracker said this dude couldn't be written
|
|
SWWriteState = STATE_IDLE;
|
|
|
|
if(sw_resp != nullptr){
|
|
memcpy(sw_resp, &SquadWarWriteResponse, sizeof(squad_war_response));
|
|
}
|
|
return 3;
|
|
}
|
|
|
|
if(SWWriteState == STATE_TIMED_OUT){
|
|
// We gave up on sending this pilot, and now we are about to inform the app, so back to idle
|
|
SWWriteState = STATE_IDLE;
|
|
|
|
return -1;
|
|
}
|
|
} else if(sw_res == reinterpret_cast<squad_war_result *>(static_cast<uintptr_t>(0xffffffff))){
|
|
if(SWWriteState == STATE_IDLE){
|
|
return -3;
|
|
} else {
|
|
// Cancel this baby
|
|
SWWriteState = STATE_IDLE;
|
|
|
|
return 2;
|
|
}
|
|
} else if(SWWriteState == STATE_IDLE) {
|
|
//New request, send out the req, and go for it.
|
|
|
|
SWWriteState = STATE_SENDING_PILOT;
|
|
|
|
SWLastSentWrite = 0;
|
|
SWFirstSentWrite = timer_get_milliseconds();
|
|
|
|
sw_res_write.len = PACKED_HEADER_ONLY_SIZE+sizeof(squad_war_result);
|
|
sw_res_write.type = UNT_SW_RESULT_WRITE;
|
|
sw_res_write.code = CMD_GAME_FS2OPEN;
|
|
memcpy(&sw_res_write.data, sw_res, sizeof(squad_war_result));
|
|
|
|
return 0;
|
|
}
|
|
return -2;
|
|
}
|
|
|
|
|
|
// Returns:
|
|
// -3 Error -- Called with NULL, but no request is waiting
|
|
// -2 Error -- Already waiting on data (hasn't timed out yet)
|
|
// -1 Timeout waiting for pilot data
|
|
// 0 Waiting for data
|
|
// 1 Data received
|
|
// 2 Get Cancelled
|
|
// 3 Pilot not found
|
|
|
|
// Call with NULL to poll
|
|
// Call with -1 to cancel wait
|
|
// Call with valid pointer to a vmt_descent3_struct to get a response
|
|
int GetFSPilotData(vmt_stats_struct *fs_pilot, const char *pilot_name, const char *tracker_id, int get_security)
|
|
{
|
|
//First check the network
|
|
PollPTrackNet();
|
|
|
|
if(fs_pilot == nullptr)
|
|
{
|
|
if(FSReadState == STATE_IDLE)
|
|
{
|
|
return -3;
|
|
}
|
|
if(FSReadState == STATE_READING_PILOT)
|
|
{
|
|
return 0;
|
|
}
|
|
if(FSReadState == STATE_RECEIVED_PILOT)
|
|
{
|
|
// We got this pilot, and now we are about to inform the app, so back to idle
|
|
FSReadState = STATE_IDLE;
|
|
ReadFSPilot = nullptr;
|
|
return 1;
|
|
}
|
|
if(FSReadState == STATE_TIMED_OUT)
|
|
{
|
|
// We gave up on this pilot, and now we are about to inform the app, so back to idle
|
|
FSReadState = STATE_IDLE;
|
|
ReadFSPilot = nullptr;
|
|
return -1;
|
|
}
|
|
if(FSReadState == STATE_PILOT_NOT_FOUND)
|
|
{
|
|
//The tracker said this dude is not found.
|
|
FSReadState = STATE_IDLE;
|
|
ReadFSPilot = nullptr;
|
|
return 3;
|
|
}
|
|
|
|
}
|
|
else if(fs_pilot == reinterpret_cast<vmt_stats_struct *>(static_cast<uintptr_t>(0xffffffff)))
|
|
{
|
|
if(FSReadState == STATE_IDLE)
|
|
{
|
|
return -3;
|
|
}
|
|
else
|
|
{
|
|
//Cancel this baby
|
|
FSReadState = STATE_IDLE;
|
|
ReadFSPilot = nullptr;
|
|
return 2;
|
|
}
|
|
|
|
}
|
|
else if(FSReadState == STATE_IDLE)
|
|
{
|
|
//New request, send out the req, and go for it.
|
|
|
|
FSReadState = STATE_READING_PILOT;
|
|
ReadFSPilot = fs_pilot;
|
|
FSLastSent = 0;
|
|
FSFirstSent = timer_get_milliseconds();
|
|
|
|
fs_pilot_req.xcode = static_cast<unsigned short>(Multi_fs_tracker_game_id);
|
|
fs_pilot_req.len = PACKED_HEADER_ONLY_SIZE+sizeof(pilot_request);
|
|
|
|
if(get_security){
|
|
fs_pilot_req.type = UNT_PILOT_DATA_READ_NEW;
|
|
} else {
|
|
fs_pilot_req.type = UNT_PILOT_DATA_READ;
|
|
}
|
|
|
|
fs_pilot_req.code = CMD_GAME_FS2OPEN;
|
|
SDL_strlcpy(fs_pr->pilot_name, pilot_name, SDL_arraysize(fs_pr->pilot_name));
|
|
SDL_strlcpy(fs_pr->tracker_id, tracker_id, SDL_arraysize(fs_pr->tracker_id));
|
|
|
|
return 0;
|
|
}
|
|
return -2;
|
|
|
|
}
|
|
|
|
// Send an ACK to the server
|
|
void AckServer(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 = SerializePilotPacket(&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>(&ptrackaddr), sizeof(ptrackaddr), PSNET_TYPE_USER_TRACKER);
|
|
}
|
|
|
|
void IdlePTrack()
|
|
{
|
|
ubyte packet_data[sizeof(udp_packet_header)];
|
|
int packet_length = 0;
|
|
|
|
PSNET_TOP_LAYER_PROCESS();
|
|
|
|
// reading pilot data
|
|
if(FSReadState == STATE_READING_PILOT){
|
|
if((timer_get_milliseconds()-FSFirstSent)>=PILOT_REQ_TIMEOUT){
|
|
FSReadState = STATE_TIMED_OUT;
|
|
} else if((timer_get_milliseconds()-FSLastSent)>=PILOT_REQ_RESEND_TIME){
|
|
//Send 'da packet
|
|
packet_length = SerializePilotPacket(&fs_pilot_req, packet_data);
|
|
SENDTO(Psnet_socket, reinterpret_cast<char *>(&packet_data), packet_length, 0,
|
|
reinterpret_cast<LPSOCKADDR>(&ptrackaddr), sizeof(ptrackaddr), PSNET_TYPE_USER_TRACKER);
|
|
|
|
FSLastSent = timer_get_milliseconds();
|
|
}
|
|
}
|
|
|
|
// writing pilot data
|
|
if(FSWriteState == STATE_SENDING_PILOT){
|
|
if((timer_get_milliseconds()-FSFirstSentWrite)>=PILOT_REQ_TIMEOUT){
|
|
FSWriteState = STATE_TIMED_OUT;
|
|
|
|
} else if((timer_get_milliseconds()-FSLastSentWrite)>=PILOT_REQ_RESEND_TIME){
|
|
// Send 'da packet
|
|
packet_length = SerializePilotPacket(&fs_pilot_write, packet_data);
|
|
SENDTO(Psnet_socket, reinterpret_cast<char *>(&packet_data), packet_length, 0,
|
|
reinterpret_cast<LPSOCKADDR>(&ptrackaddr), sizeof(ptrackaddr), PSNET_TYPE_USER_TRACKER);
|
|
|
|
FSLastSentWrite = timer_get_milliseconds();
|
|
}
|
|
}
|
|
|
|
// writing squad war results
|
|
if(SWWriteState == STATE_SENDING_PILOT){
|
|
if((timer_get_milliseconds()-SWFirstSentWrite) >= PILOT_REQ_TIMEOUT){
|
|
SWWriteState = STATE_TIMED_OUT;
|
|
} else if((timer_get_milliseconds()-SWLastSentWrite) >= PILOT_REQ_RESEND_TIME){
|
|
// Send 'da packet
|
|
packet_length = SerializePilotPacket(&sw_res_write, packet_data);
|
|
SENDTO(Psnet_socket, reinterpret_cast<char *>(&packet_data), packet_length, 0,
|
|
reinterpret_cast<LPSOCKADDR>(&ptrackaddr), sizeof(ptrackaddr), PSNET_TYPE_USER_TRACKER);
|
|
|
|
SWLastSentWrite = timer_get_milliseconds();
|
|
}
|
|
}
|
|
}
|
|
|
|
void PollPTrackNet()
|
|
{
|
|
fd_set read_fds;
|
|
struct timeval timeout;
|
|
ubyte packet_data[sizeof(udp_packet_header)];
|
|
|
|
IdlePTrack();
|
|
|
|
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_USER_TRACKER)){
|
|
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_USER_TRACKER);
|
|
|
|
if (bytesin > 0) {
|
|
DeserializePilotPacket(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
|
|
}
|
|
|
|
//Check to make sure the packets ok
|
|
if ( (bytesin > 0) && (bytesin == inpacket.len) ) {
|
|
switch(inpacket.type){
|
|
case UNT_PILOT_DATA_RESPONSE:
|
|
if(inpacket.code == CMD_GAME_FS2OPEN){
|
|
if(FSReadState == STATE_READING_PILOT){
|
|
vmt_stats_struct *stats;
|
|
|
|
// 9/17/98 MWA. Compare the tracker id of this packet with the tracker id of
|
|
// what we are expecting. Only set our state to something different when
|
|
// the tracker id's match. This fixes possible multiple packets for a single pilto
|
|
// accidentally getting set for the wrong pilot
|
|
|
|
stats = reinterpret_cast<vmt_stats_struct *>(&inpacket.data);
|
|
if ( stats->tracker_id == SDL_atoi(fs_pr->tracker_id) ) {
|
|
//Copy the data
|
|
memcpy(ReadFSPilot,&inpacket.data,sizeof(vmt_stats_struct));
|
|
//Set the state
|
|
FSReadState = STATE_RECEIVED_PILOT;
|
|
}
|
|
}
|
|
} else {
|
|
Int3();
|
|
}
|
|
break;
|
|
|
|
case UNT_PILOT_READ_FAILED:
|
|
if(inpacket.code == CMD_GAME_FS2OPEN){
|
|
if(FSReadState == STATE_READING_PILOT){
|
|
FSReadState = STATE_PILOT_NOT_FOUND;
|
|
}
|
|
} else {
|
|
Int3();
|
|
}
|
|
break;
|
|
|
|
case UNT_PILOT_WRITE_SUCCESS:
|
|
if(inpacket.code == CMD_GAME_FS2OPEN){
|
|
if(FSWriteState == STATE_SENDING_PILOT){
|
|
FSWriteState = STATE_WROTE_PILOT;
|
|
}
|
|
} else {
|
|
Int3();
|
|
}
|
|
break;
|
|
|
|
case UNT_PILOT_WRITE_FAILED:
|
|
if(inpacket.code == CMD_GAME_FS2OPEN){
|
|
if(FSWriteState == STATE_SENDING_PILOT){
|
|
FSWriteState = STATE_WRITE_PILOT_FAILED;
|
|
}
|
|
} else {
|
|
Int3();
|
|
}
|
|
break;
|
|
|
|
case UNT_SW_RESULT_RESPONSE:
|
|
if(SWWriteState == STATE_SENDING_PILOT){
|
|
// copy the data
|
|
Assert((bytesin - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response));
|
|
if((bytesin - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response)){
|
|
memset(&SquadWarWriteResponse, 0, sizeof(squad_war_response));
|
|
memcpy(&SquadWarWriteResponse, inpacket.data, sizeof(squad_war_response));
|
|
|
|
// now check to see if we're good
|
|
if(SquadWarWriteResponse.accepted){
|
|
SWWriteState = STATE_WROTE_PILOT;
|
|
} else {
|
|
SWWriteState = STATE_WRITE_PILOT_FAILED;
|
|
}
|
|
} else {
|
|
SWWriteState = STATE_WRITE_PILOT_FAILED;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UNT_CONTROL:
|
|
Int3();
|
|
break;
|
|
|
|
case UNT_CONTROL_VALIDATION:
|
|
Int3();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
AckServer(inpacket.sig);
|
|
}
|
|
}
|
|
}
|