]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/ptrack.cpp
fix various code issues
[taylor/freespace2.git] / src / network / ptrack.cpp
1 /*
2  * Copyright (C) Volition, Inc. 2005.  All rights reserved.
3  * 
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on the 
6  * source.
7  *
8 */
9
10 //Pilot tracker client code
11
12 #ifdef PLAT_UNIX
13 #include <arpa/inet.h>
14 #include <netinet/in.h>
15 #include <errno.h>
16 #include <netdb.h>
17 #endif
18
19 #include "pstypes.h"
20 #include "timer.h"
21 #include "multi.h"
22 #include "ptrack.h"
23 #include "psnet.h"
24
25
26 // check structs for size compatibility
27 //SDL_COMPILE_TIME_ASSERT(udp_packet_header, sizeof(udp_packet_header) == 497);
28 #ifndef MAKE_FS1
29 #ifdef FS2_DEMO
30 SDL_COMPILE_TIME_ASSERT(vmt_freespace2_struct, sizeof(vmt_freespace2_struct) == 408);
31 #else
32 SDL_COMPILE_TIME_ASSERT(vmt_freespace2_struct, sizeof(vmt_freespace2_struct) == 440);
33 #endif
34 #else
35 SDL_COMPILE_TIME_ASSERT(vmt_freespace_struct, sizeof(vmt_freespace_struct) == 468);
36 #endif
37 SDL_COMPILE_TIME_ASSERT(validate_id_request, sizeof(validate_id_request) == 60);
38 SDL_COMPILE_TIME_ASSERT(squad_war_request, sizeof(squad_war_request) == 104);
39 SDL_COMPILE_TIME_ASSERT(squad_war_response, sizeof(squad_war_response) == 256);
40 SDL_COMPILE_TIME_ASSERT(squad_war_result, sizeof(squad_war_result) == 72);
41 SDL_COMPILE_TIME_ASSERT(pilot_request, sizeof(pilot_request) == 32);
42
43
44 //Variables
45
46 #ifdef MAKE_FS1
47 SOCKET  pilotsock;
48 #define PILOTSOCK pilotsock
49 #else
50 #define PILOTSOCK Unreliable_socket
51 #endif
52
53 struct sockaddr_in      ptrackaddr;
54
55
56 int             FSWriteState;
57 int             FSReadState;
58 unsigned int    FSLastSentWrite;
59 unsigned int    FSFirstSentWrite;
60 unsigned int    FSLastSent;
61 unsigned int    FSFirstSent;
62
63 int             SWWriteState;
64 unsigned int SWLastSentWrite;
65 unsigned int SWFirstSentWrite;
66
67
68 udp_packet_header fs_pilot_req, fs_pilot_write, sw_res_write;
69 pilot_request *fs_pr;
70 #ifdef MAKE_FS1
71 vmt_freespace_struct *ReadFSPilot;
72 #else
73 vmt_freespace2_struct *ReadFSPilot;
74 #endif
75
76 // squad war response
77 squad_war_response SquadWarWriteResponse;
78
79
80 static int SerializePilotPacket(const udp_packet_header *uph, ubyte *data)
81 {
82         int packet_size = 0;
83         int i;
84 #ifdef MAKE_FS1
85         char h_pad = 0;
86 #endif
87
88         PXO_ADD_DATA(uph->type);
89 #ifdef MAKE_FS1
90         PXO_ADD_DATA(h_pad);
91 #endif
92         PXO_ADD_USHORT(uph->len);
93         PXO_ADD_UINT(uph->code);
94         PXO_ADD_USHORT(uph->xcode);
95 #ifdef MAKE_FS1
96         PXO_ADD_DATA(h_pad);
97         PXO_ADD_DATA(h_pad);
98 #endif
99         PXO_ADD_UINT(uph->sig);
100         PXO_ADD_UINT(uph->security);
101
102         switch (uph->type) {
103                 // no extra data for this
104                 case UNT_CONTROL:
105                         break;
106
107                 case UNT_PILOT_DATA_WRITE_NEW: {
108                         vmt_stats_struct *fs2 = (vmt_stats_struct *)&uph->data;
109
110                         PXO_ADD_DATA(fs2->tracker_id);
111                         PXO_ADD_DATA(fs2->pilot_name);
112
113                         PXO_ADD_DATA(fs2->pad_a);       // junk, for size/alignment
114
115                         PXO_ADD_INT(fs2->score);
116                         PXO_ADD_INT(fs2->rank);
117
118 #ifdef MAKE_FS1
119                         for (i = 0; i < MAX_FS_MEDALS; i++) {
120                                 PXO_ADD_INT(fs2->medals[i]);
121                         }
122
123                         for (i = 0; i < MAX_FS_SHIP_TYPES; i++) {
124                                 PXO_ADD_INT(fs2->kills[i]);
125                         }
126 #elif defined(FS2_DEMO)
127                         for (i = 0; i < MAX_FS2_MEDALS; i++) {
128                                 PXO_ADD_INT(fs2->medals[i]);
129                         }
130
131                         for (i = 0; i < MAX_FS2_SHIP_TYPES; i++) {
132                                 PXO_ADD_USHORT(fs2->kills[i]);
133                         }
134 #endif
135
136                         PXO_ADD_INT(fs2->assists);
137                         PXO_ADD_INT(fs2->kill_count);
138                         PXO_ADD_INT(fs2->kill_count_ok);
139                         PXO_ADD_UINT(fs2->p_shots_fired);
140                         PXO_ADD_UINT(fs2->s_shots_fired);
141
142                         PXO_ADD_UINT(fs2->p_shots_hit);
143                         PXO_ADD_UINT(fs2->s_shots_hit);
144
145                         PXO_ADD_UINT(fs2->p_bonehead_hits);
146                         PXO_ADD_UINT(fs2->s_bonehead_hits);
147                         PXO_ADD_INT(fs2->bonehead_kills);
148
149                         PXO_ADD_INT(fs2->security);
150                         PXO_ADD_DATA(fs2->virgin_pilot);
151
152                         PXO_ADD_DATA(fs2->pad_b);       // junk, for size/alignment
153
154                         PXO_ADD_UINT(fs2->checksum);
155
156                         PXO_ADD_UINT(fs2->missions_flown);
157                         PXO_ADD_UINT(fs2->flight_time);
158                         PXO_ADD_UINT(fs2->last_flown);
159
160 #if !defined(MAKE_FS1) && !defined(FS2_DEMO)
161                         PXO_ADD_USHORT(fs2->num_medals);
162                         PXO_ADD_USHORT(fs2->num_ship_types);
163
164                         for (i = 0; i < MAX_FS2_MEDALS; i++) {
165                                 PXO_ADD_INT(fs2->medals[i]);
166                         }
167
168                         for (i = 0; i < MAX_FS2_SHIP_TYPES; i++) {
169                                 PXO_ADD_USHORT(fs2->kills[i]);
170                         }
171 #endif
172
173                         break;
174                 }
175
176                 case UNT_SW_RESULT_WRITE: {
177                         squad_war_result *sw_result     = (squad_war_result *)&uph->data;
178
179                         PXO_ADD_DATA(sw_result->match_code);
180                         PXO_ADD_DATA(sw_result->result);
181                         PXO_ADD_DATA(sw_result->squad_count1);
182                         PXO_ADD_DATA(sw_result->squad_count2);
183                         PXO_ADD_DATA(sw_result->pad);           // junk, for size/alignment
184
185                         for (i = 0; i < MAX_SQUAD_PLAYERS; i++) {
186                                 PXO_ADD_INT(sw_result->squad_winners[i]);
187                         }
188
189                         for (i = 0; i < MAX_SQUAD_PLAYERS; i++) {
190                                 PXO_ADD_INT(sw_result->squad_losers[i]);
191                         }
192
193                         break;
194                 }
195
196                 case UNT_PILOT_DATA_READ_NEW:
197                 case UNT_PILOT_DATA_READ: {
198                         pilot_request *pr = (pilot_request *)&uph->data;
199
200                         PXO_ADD_DATA(pr->pilot_name);
201                         PXO_ADD_DATA(pr->tracker_id);
202                         PXO_ADD_DATA(pr->pad);          // junk, for size/alignment
203
204                         break;
205                 }
206
207                 // we shouldn't be sending any other packet types
208                 default:
209                         Int3();
210                         break;
211         }
212
213         SDL_assert(packet_size >= (int)PACKED_HEADER_ONLY_SIZE);
214         SDL_assert(packet_size == (int)uph->len);
215
216         return packet_size;
217 }
218
219 static void DeserializePilotPacket(const ubyte *data, const int data_size, udp_packet_header *uph)
220 {
221         int offset = 0;
222         int i;
223 #ifdef MAKE_FS1
224         char h_pad;
225 #endif
226
227         memset(uph, 0, sizeof(udp_packet_header));
228
229         // make sure we received a complete base packet
230         if (data_size < (int)PACKED_HEADER_ONLY_SIZE) {
231                 uph->len = 0;
232                 uph->type = 0xff;
233
234                 return;
235         }
236
237         PXO_GET_DATA(uph->type);
238 #ifdef MAKE_FS1
239         PXO_GET_DATA(h_pad);
240 #endif
241         PXO_GET_USHORT(uph->len);
242         PXO_GET_UINT(uph->code);
243         PXO_GET_USHORT(uph->xcode);
244 #ifdef MAKE_FS1
245         PXO_GET_DATA(h_pad);
246         PXO_GET_DATA(h_pad);
247 #endif
248         PXO_GET_UINT(uph->sig);
249         PXO_GET_UINT(uph->security);
250
251         // sanity check data size to make sure we reveived all of the expected packet
252 #ifndef MAKE_FS1
253         // (the -1 is because psnet2 pops off one byte)
254         if ((int)uph->len-1 > data_size) {
255 #else
256         if ((int)uph->len > data_size) {
257 #endif
258                 uph->len = 0;
259                 uph->type = 0xff;
260
261                 return;
262         }
263
264         switch (uph->type) {
265                 // no extra data for these
266                 case UNT_PILOT_READ_FAILED:
267                 case UNT_PILOT_WRITE_SUCCESS:
268                 case UNT_PILOT_WRITE_FAILED:
269                         break;
270
271                 case UNT_PILOT_DATA_RESPONSE: {
272                         vmt_stats_struct *fs2 = (vmt_stats_struct *)&uph->data;
273
274                         PXO_GET_DATA(fs2->tracker_id);
275                         PXO_GET_DATA(fs2->pilot_name);
276
277                         PXO_GET_DATA(fs2->pad_a);       // junk, for size/alignment
278
279                         PXO_GET_INT(fs2->score);
280                         PXO_GET_INT(fs2->rank);
281
282 #ifdef MAKE_FS1
283                         for (i = 0; i < MAX_FS_MEDALS; i++) {
284                                 PXO_GET_INT(fs2->medals[i]);
285                         }
286
287                         for (i =0; i < MAX_FS_SHIP_TYPES; i++) {
288                                 PXO_GET_INT(fs2->kills[i]);
289                         }
290 #elif defined(FS2_DEMO)
291                         for (i = 0; i < MAX_FS2_MEDALS; i++) {
292                                 PXO_GET_INT(fs2->medals[i]);
293                         }
294
295                         for (i =0; i < MAX_FS2_SHIP_TYPES; i++) {
296                                 PXO_GET_USHORT(fs2->kills[i]);
297                         }
298 #endif
299
300                         PXO_GET_INT(fs2->assists);
301                         PXO_GET_INT(fs2->kill_count);
302                         PXO_GET_INT(fs2->kill_count_ok);
303                         PXO_GET_UINT(fs2->p_shots_fired);
304                         PXO_GET_UINT(fs2->s_shots_fired);
305
306                         PXO_GET_UINT(fs2->p_shots_hit);
307                         PXO_GET_UINT(fs2->s_shots_hit);
308
309                         PXO_GET_UINT(fs2->p_bonehead_hits);
310                         PXO_GET_UINT(fs2->s_bonehead_hits);
311                         PXO_GET_INT(fs2->bonehead_kills);
312
313                         PXO_GET_INT(fs2->security);
314                         PXO_GET_DATA(fs2->virgin_pilot);
315
316                         PXO_GET_DATA(fs2->pad_b);       // junk, for size/alignment
317
318                         PXO_GET_UINT(fs2->checksum);
319
320                         PXO_GET_UINT(fs2->missions_flown);
321                         PXO_GET_UINT(fs2->flight_time);
322                         PXO_GET_UINT(fs2->last_flown);
323
324 #if !defined(MAKE_FS1) && !defined(FS2_DEMO)
325                         PXO_GET_USHORT(fs2->num_medals);
326                         PXO_GET_USHORT(fs2->num_ship_types);
327
328                         for (i = 0; i < MAX_FS2_MEDALS; i++) {
329                                 PXO_GET_INT(fs2->medals[i]);
330                         }
331
332                         for (i =0; i < MAX_FS2_SHIP_TYPES; i++) {
333                                 PXO_GET_USHORT(fs2->kills[i]);
334                         }
335 #endif
336
337                         break;
338                 }
339
340                 case UNT_SW_RESULT_RESPONSE: {
341                         squad_war_response *sw_resp = (squad_war_response *)&uph->data;
342
343                         PXO_GET_DATA(sw_resp->reason);
344                         PXO_GET_DATA(sw_resp->accepted);
345
346                         break;
347                 }
348
349                 default:
350                         break;
351         }
352
353         //SDL_assert(offset == data_size);
354 }
355
356
357 int InitPilotTrackerClient()
358 {
359         struct sockaddr_in sockaddr;
360         in_addr_t iaddr;
361
362         FSWriteState = STATE_IDLE;
363         FSReadState = STATE_IDLE;       
364         SWWriteState = STATE_IDLE;
365         
366         ReadFSPilot = NULL;
367
368         fs_pr = (pilot_request *)&fs_pilot_req.data;
369
370 #ifdef MAKE_FS1
371         pilotsock = socket(AF_INET,SOCK_DGRAM,0);
372         
373         if ( pilotsock == (SOCKET)INVALID_SOCKET )
374         {
375                 mprintf(("Unable to open a socket.\n"));
376                 return 0;
377         }
378 #endif
379         
380         memset( &sockaddr, 0, sizeof(struct sockaddr_in) );
381         sockaddr.sin_family = AF_INET; 
382         sockaddr.sin_addr.s_addr = INADDR_ANY; 
383         sockaddr.sin_port = 0;//htons(REGPORT);
384         
385 #ifdef MAKE_FS1
386         if (SOCKET_ERROR==bind(pilotsock, (struct sockaddr*)&sockaddr, sizeof (sockaddr)))
387         {       
388                 mprintf(("Unable to bind a socket.\n"));
389                 mprintf(("WSAGetLastError() returned %d.\n",WSAGetLastError()));
390                 return 0;
391         }
392 #endif
393         
394         // iaddr = inet_addr ( Multi_user_tracker_ip_address ); 
395
396         // first try and resolve by name
397         iaddr = inet_addr( Multi_options_g.user_tracker_ip );
398         if ( iaddr == INADDR_NONE ) {
399                 struct hostent *he;
400                 he = gethostbyname( Multi_options_g.user_tracker_ip );
401                 if(!he)
402                         return 0;
403         /*
404                 {               
405                         // try and resolve by address
406                         unsigned int n_order = inet_addr(Multi_user_tracker_ip_address);
407                         he = gethostbyaddr((char*)&n_order,4,PF_INET);
408
409                         if(!he){
410                                 return 0;
411                         }
412                 }
413         */
414                 iaddr = ((in_addr *)(he->h_addr))->s_addr;
415         }
416         
417         ptrackaddr.sin_addr.s_addr = iaddr;
418         ptrackaddr.sin_family = AF_INET; 
419         ptrackaddr.sin_port = htons(REGPORT);
420         
421         return 1;
422 }
423
424 // Returns:
425 // -3   Error -- Called with NULL, but no request is waiting
426 // -2   Error -- Already sending data (hasn't timed out yet)
427 // -1   Timeout trying to send pilot data
428 // 0    Sending
429 // 1    Data succesfully sent
430 // 2    Send Cancelled (data may still have been written already, we just haven't been ACK'd yet)
431 // 3    Pilot not written (for some reason)
432   
433 // Call with NULL to poll 
434 // Call with -1 to cancel send
435 // Call with valid pointer to a vmt_descent3_struct to initiate send
436 int SendFSPilotData(vmt_stats_struct *fs_pilot)
437 {
438         //First check the network
439         PollPTrackNet();
440
441         if(fs_pilot == NULL)
442         {
443                 if(FSWriteState == STATE_IDLE)
444                 {
445                         return -3;
446                 }
447                 if(FSWriteState == STATE_SENDING_PILOT)
448                 {
449                         return 0;
450                 }
451                 if(FSWriteState == STATE_WROTE_PILOT)
452                 {
453                         //We wrote this pilot, and now we are about to inform the app, so back to idle
454                         FSWriteState = STATE_IDLE;
455                         return 1;
456                 }
457                 if(FSWriteState == STATE_TIMED_OUT)
458                 {
459                         //We gave up on sending this pilot, and now we are about to inform the app, so back to idle
460                         FSWriteState = STATE_IDLE;
461
462                         return -1;
463                 }
464                 if(FSWriteState == STATE_WRITE_PILOT_FAILED)
465                 {
466                         //The tracker said this dude couldn't be written
467                         FSWriteState = STATE_IDLE;
468
469                         return 3;
470                 }
471
472         }
473         else if(fs_pilot == (vmt_stats_struct*)0xffffffff)
474         {
475                 if(FSWriteState == STATE_IDLE)
476                 {
477                         return -3;
478                 }
479                 else
480                 {
481                         //Cancel this baby
482                         FSWriteState = STATE_IDLE;
483
484                         return 2;
485                 }
486
487         }
488         else if(FSWriteState == STATE_IDLE)
489         {
490                 //New request, send out the req, and go for it.
491                 
492                 FSWriteState = STATE_SENDING_PILOT;
493                 
494                 FSLastSentWrite = 0;
495                 FSFirstSentWrite = timer_get_milliseconds();
496
497                 fs_pilot_write.type = UNT_PILOT_DATA_WRITE_NEW;
498 #ifdef MAKE_FS1
499                 fs_pilot_write.code = CMD_GAME_FREESPACE;
500 #else
501                 fs_pilot_write.code = CMD_GAME_FREESPACE2;
502 #endif
503                 fs_pilot_write.len = PACKED_HEADER_ONLY_SIZE+sizeof(vmt_stats_struct);
504                 memcpy(&fs_pilot_write.data,fs_pilot,sizeof(vmt_stats_struct));
505
506                 return 0;       
507         }
508         return -2;
509 }
510
511 // Returns:
512 // -3   Error -- Called with NULL, but no request is waiting
513 // -2   Error -- Already sending data (hasn't timed out yet)
514 // -1   Timeout trying to send pilot data
515 // 0    Sending
516 // 1    Data succesfully sent
517 // 2    Send Cancelled (data may still have been written already, we just haven't been ACK'd yet)
518 // 3    Pilot not written (for some reason)
519   
520 // Call with NULL to poll 
521 // Call with -1 to cancel send
522 // Call with valid pointer to a vmt_descent3_struct to initiate send
523 int SendSWData(squad_war_result *sw_res, squad_war_response *sw_resp)
524 {
525         //First check the network
526         PollPTrackNet();
527
528         if(sw_res == NULL){
529                 if(SWWriteState == STATE_IDLE){
530                         return -3;
531                 }
532                 if(SWWriteState == STATE_SENDING_PILOT){
533                         return 0;
534                 }
535
536                 // fill in the response
537                 if(SWWriteState == STATE_WROTE_PILOT){
538                         // We wrote this pilot, and now we are about to inform the app, so back to idle
539                         SWWriteState = STATE_IDLE;
540                         
541                         if(sw_resp != NULL){
542                                 memcpy(sw_resp, &SquadWarWriteResponse, sizeof(squad_war_response));
543                         }
544                         return 1;
545                 }
546                 // fill in the response
547                 if(SWWriteState == STATE_WRITE_PILOT_FAILED){
548                         // The tracker said this dude couldn't be written               
549                         SWWriteState = STATE_IDLE;
550
551                         if(sw_resp != NULL){
552                                 memcpy(sw_resp, &SquadWarWriteResponse, sizeof(squad_war_response));
553                         }
554                         return 3;
555                 }
556
557                 if(SWWriteState == STATE_TIMED_OUT){
558                         // We gave up on sending this pilot, and now we are about to inform the app, so back to idle
559                         SWWriteState = STATE_IDLE;
560
561                         return -1;
562                 }               
563         } else if(sw_res == (squad_war_result*)0xffffffff){
564                 if(SWWriteState == STATE_IDLE){
565                         return -3;
566                 } else {
567                         // Cancel this baby
568                         SWWriteState = STATE_IDLE;
569
570                         return 2;
571                 }
572         } else if(SWWriteState == STATE_IDLE) {
573                 //New request, send out the req, and go for it.
574                 
575                 SWWriteState = STATE_SENDING_PILOT;
576                 
577                 SWLastSentWrite = 0;
578                 SWFirstSentWrite = timer_get_milliseconds();
579
580                 sw_res_write.len = PACKED_HEADER_ONLY_SIZE+sizeof(squad_war_result);
581                 sw_res_write.type = UNT_SW_RESULT_WRITE;
582 #ifdef MAKE_FS1
583                 sw_res_write.code = CMD_GAME_FREESPACE;
584 #else
585                 sw_res_write.code = CMD_GAME_FREESPACE2;
586 #endif
587                 memcpy(&sw_res_write.data, sw_res, sizeof(squad_war_result));
588
589                 return 0;       
590         }
591         return -2;
592 }
593
594
595 // Returns:
596 // -3   Error -- Called with NULL, but no request is waiting
597 // -2   Error -- Already waiting on data (hasn't timed out yet)
598 // -1   Timeout waiting for pilot data
599 // 0    Waiting for data
600 // 1    Data received
601 // 2    Get Cancelled
602 // 3    Pilot not found
603         
604 // Call with NULL to poll 
605 // Call with -1 to cancel wait
606 // Call with valid pointer to a vmt_descent3_struct to get a response
607 int GetFSPilotData(vmt_stats_struct *fs_pilot, const char *pilot_name, const char *tracker_id, int get_security)
608 {
609         //First check the network
610         PollPTrackNet();
611
612         if(fs_pilot == NULL)
613         {
614                 if(FSReadState == STATE_IDLE)
615                 {
616                         return -3;
617                 }
618                 if(FSReadState == STATE_READING_PILOT)
619                 {
620                         return 0;
621                 }
622                 if(FSReadState == STATE_RECEIVED_PILOT)
623                 {
624                         // We got this pilot, and now we are about to inform the app, so back to idle
625                         FSReadState = STATE_IDLE;
626                         ReadFSPilot = NULL;
627                         return 1;
628                 }
629                 if(FSReadState == STATE_TIMED_OUT)
630                 {
631                         // We gave up on this pilot, and now we are about to inform the app, so back to idle
632                         FSReadState = STATE_IDLE;
633                         ReadFSPilot = NULL;
634                         return -1;
635                 }
636                 if(FSReadState == STATE_PILOT_NOT_FOUND)
637                 {
638                         //The tracker said this dude is not found.
639                         FSReadState = STATE_IDLE;
640                         ReadFSPilot = NULL;
641                         return 3;
642                 }
643
644         }
645         else if(fs_pilot == (vmt_stats_struct*)0xffffffff)
646         {
647                 if(FSReadState == STATE_IDLE)
648                 {
649                         return -3;
650                 }
651                 else
652                 {
653                         //Cancel this baby
654                         FSReadState = STATE_IDLE;
655                         ReadFSPilot = NULL;
656                         return 2;
657                 }
658
659         }
660         else if(FSReadState == STATE_IDLE)
661         {
662                 //New request, send out the req, and go for it.
663                 
664                 FSReadState = STATE_READING_PILOT;
665                 ReadFSPilot = fs_pilot;
666                 FSLastSent = 0;
667                 FSFirstSent = timer_get_milliseconds();
668
669                 fs_pilot_req.len = PACKED_HEADER_ONLY_SIZE+sizeof(pilot_request);
670
671                 if(get_security){
672                         fs_pilot_req.type = UNT_PILOT_DATA_READ_NEW;
673                 } else {
674                         fs_pilot_req.type = UNT_PILOT_DATA_READ;                        
675                 }
676
677 #ifdef MAKE_FS1
678                 fs_pilot_req.code = CMD_GAME_FREESPACE;
679 #else
680                 fs_pilot_req.code = CMD_GAME_FREESPACE2;
681 #endif
682                 SDL_strlcpy(fs_pr->pilot_name, pilot_name, SDL_arraysize(fs_pr->pilot_name));
683                 SDL_strlcpy(fs_pr->tracker_id, tracker_id, SDL_arraysize(fs_pr->tracker_id));
684
685                 return 0;       
686         }
687         return -2;
688
689 }
690
691 // Send an ACK to the server
692 void AckServer(unsigned int sig)
693 {
694         udp_packet_header ack_pack;
695         ubyte packet_data[sizeof(udp_packet_header)];
696         int packet_length = 0;
697
698         ack_pack.type = UNT_CONTROL;
699         ack_pack.sig = sig;
700         ack_pack.code = CMD_CLIENT_RECEIVED;
701         ack_pack.len = PACKED_HEADER_ONLY_SIZE; 
702
703         packet_length = SerializePilotPacket(&ack_pack, packet_data);
704         SDL_assert(packet_length == PACKED_HEADER_ONLY_SIZE);
705         PXO_SENDTO(PILOTSOCK, (char *)&packet_data, packet_length, 0, (struct sockaddr *)&ptrackaddr, sizeof(struct sockaddr_in), PSNET_TYPE_USER_TRACKER);
706 }
707
708 void IdlePTrack()
709 {
710         ubyte packet_data[sizeof(udp_packet_header)];
711         int packet_length = 0;
712
713 #ifndef MAKE_FS1
714         PSNET_TOP_LAYER_PROCESS();
715 #endif
716
717         // reading pilot data
718         if(FSReadState == STATE_READING_PILOT){
719                 if((timer_get_milliseconds()-FSFirstSent)>=PILOT_REQ_TIMEOUT){
720                         FSReadState = STATE_TIMED_OUT;
721                 } else if((timer_get_milliseconds()-FSLastSent)>=PILOT_REQ_RESEND_TIME){
722                         //Send 'da packet
723                         packet_length = SerializePilotPacket(&fs_pilot_req, packet_data);
724                         PXO_SENDTO(PILOTSOCK, (char *)&packet_data, packet_length, 0, (struct sockaddr *)&ptrackaddr, sizeof(struct sockaddr_in), PSNET_TYPE_USER_TRACKER);
725                         FSLastSent = timer_get_milliseconds();
726                 }
727         }
728
729         // writing pilot data
730         if(FSWriteState == STATE_SENDING_PILOT){
731                 if((timer_get_milliseconds()-FSFirstSentWrite)>=PILOT_REQ_TIMEOUT){
732                         FSWriteState = STATE_TIMED_OUT;
733
734                 } else if((timer_get_milliseconds()-FSLastSentWrite)>=PILOT_REQ_RESEND_TIME){
735                         // Send 'da packet
736                         packet_length = SerializePilotPacket(&fs_pilot_write, packet_data);
737                         PXO_SENDTO(PILOTSOCK, (char *)&packet_data, packet_length, 0, (struct sockaddr *)&ptrackaddr, sizeof(struct sockaddr_in), PSNET_TYPE_USER_TRACKER);
738                         FSLastSentWrite = timer_get_milliseconds();
739                 }
740         }
741
742         // writing squad war results
743         if(SWWriteState == STATE_SENDING_PILOT){
744                 if((timer_get_milliseconds()-SWFirstSentWrite) >= PILOT_REQ_TIMEOUT){
745                         SWWriteState = STATE_TIMED_OUT;
746                 } else if((timer_get_milliseconds()-SWLastSentWrite) >= PILOT_REQ_RESEND_TIME){
747                         // Send 'da packet
748                         packet_length = SerializePilotPacket(&sw_res_write, packet_data);
749                         PXO_SENDTO(PILOTSOCK, (char *)&packet_data, packet_length, 0, (struct sockaddr *)&ptrackaddr, sizeof(struct sockaddr_in), PSNET_TYPE_USER_TRACKER);
750                         SWLastSentWrite = timer_get_milliseconds();
751                 }
752         }
753 }
754
755 void PollPTrackNet()
756 {
757         fd_set read_fds;                   
758         struct timeval timeout;
759         ubyte packet_data[sizeof(udp_packet_header)];
760
761         IdlePTrack();
762         
763         timeout.tv_sec=0;            
764         timeout.tv_usec=0;
765         
766         FD_ZERO(&read_fds);
767         FD_SET(PILOTSOCK, &read_fds);
768
769         if(PXO_SELECT(PILOTSOCK+1, &read_fds,NULL,NULL,&timeout, PSNET_TYPE_USER_TRACKER)){
770                 int bytesin;
771                 int addrsize;
772                 struct sockaddr_in fromaddr;
773
774                 udp_packet_header inpacket;
775
776                 SDL_zero(inpacket);
777                 addrsize = sizeof(struct sockaddr_in);
778
779                 bytesin = PXO_RECVFROM(PILOTSOCK, (char *)&packet_data, sizeof(udp_packet_header), 0, (struct sockaddr *)&fromaddr, &addrsize, PSNET_TYPE_USER_TRACKER);
780
781                 if (bytesin > 0) {
782                         DeserializePilotPacket(packet_data, bytesin, &inpacket);
783
784 #ifndef MAKE_FS1
785                         // decrease packet size by 1
786                         inpacket.len--;
787 #endif
788 #ifndef NDEBUG
789                 } else {
790                         int wserr=WSAGetLastError();
791                         mprintf(("recvfrom() failure. WSAGetLastError() returned %d\n",wserr));
792 #endif
793                 }
794
795                 //Check to make sure the packets ok
796                 if ( (bytesin > 0) && (bytesin == inpacket.len) ) {
797                         switch(inpacket.type){
798                         case UNT_PILOT_DATA_RESPONSE:
799                                 if(inpacket.code == CMD_GAME_FREESPACE2){
800 #ifdef MAKE_FS1
801                                         Int3();
802 #else
803                                         if(FSReadState == STATE_READING_PILOT){
804                                                 vmt_freespace2_struct *stats;
805                                                 
806                                                 // 9/17/98 MWA.  Compare the tracker id of this packet with the tracker id of
807                                                 // what we are expecting.  Only set our state to something different when
808                                                 // the tracker id's match.  This fixes possible multiple packets for a single pilto
809                                                 // accidentally getting set for the wrong pilot
810
811                                                 stats = (vmt_freespace2_struct *)(&inpacket.data);
812                                                 if ( !SDL_strncasecmp(stats->tracker_id, fs_pr->tracker_id,TRACKER_ID_LEN) ) {
813                                                         //Copy the data
814                                                         memcpy(ReadFSPilot,&inpacket.data,sizeof(vmt_freespace2_struct));
815                                                         //Set the state 
816                                                         FSReadState = STATE_RECEIVED_PILOT;
817                                                 }
818                                         }
819 #endif
820                                 } else if(inpacket.code == CMD_GAME_FREESPACE){
821 #ifndef MAKE_FS1
822                                         Int3();
823 #else
824                                         if(FSReadState == STATE_READING_PILOT){
825                                                 vmt_freespace_struct *stats;
826
827                                                 // 9/17/98 MWA.  Compare the tracker id of this packet with the tracker id of
828                                                 // what we are expecting.  Only set our state to something different when
829                                                 // the tracker id's match.  This fixes possible multiple packets for a single pilto
830                                                 // accidentally getting set for the wrong pilot
831
832                                                 stats = (vmt_freespace_struct *)(&inpacket.data);
833                                                 if ( !SDL_strncasecmp(stats->tracker_id, fs_pr->tracker_id,TRACKER_ID_LEN) ) {
834                                                         //Copy the data
835                                                         memcpy(ReadFSPilot,&inpacket.data,sizeof(vmt_freespace_struct));
836                                                         //Set the state
837                                                         FSReadState = STATE_RECEIVED_PILOT;
838                                                 }
839                                         }
840 #endif
841                                 } else {
842                                         Int3();
843                                 }
844                                 break;
845
846                         case UNT_PILOT_READ_FAILED:
847                                 if(inpacket.code == CMD_GAME_FREESPACE2){
848 #ifdef MAKE_FS1
849                                         Int3();
850 #else
851                                         if(FSReadState == STATE_READING_PILOT){
852                                                 FSReadState = STATE_PILOT_NOT_FOUND;
853                                         }
854 #endif
855                                 } else if(inpacket.code == CMD_GAME_FREESPACE){
856 #ifndef MAKE_FS1
857                                         Int3();
858 #else
859                                         if(FSReadState == STATE_READING_PILOT){
860                                                 FSReadState = STATE_PILOT_NOT_FOUND;
861                                         }
862 #endif
863                                 } else {
864                                         Int3();
865                                 }
866                                 break;
867
868                         case UNT_PILOT_WRITE_SUCCESS:
869                                 if(inpacket.code == CMD_GAME_FREESPACE2){
870 #ifdef MAKE_FS1
871                                         Int3();
872 #else
873                                         if(FSWriteState == STATE_SENDING_PILOT){
874                                                 FSWriteState = STATE_WROTE_PILOT;
875                                         }
876 #endif
877                                 } else if(inpacket.code == CMD_GAME_FREESPACE){
878 #ifndef MAKE_FS1
879                                         Int3();
880 #else
881                                         if(FSWriteState == STATE_SENDING_PILOT){
882                                                 FSWriteState = STATE_WROTE_PILOT;
883                                         }
884 #endif
885                                 } else {
886                                         Int3();
887                                 }
888                                 break;
889
890                         case UNT_PILOT_WRITE_FAILED:
891                                 if(inpacket.code == CMD_GAME_FREESPACE2){
892 #ifdef MAKE_FS1
893                                         Int3();
894 #else
895                                         if(FSWriteState == STATE_SENDING_PILOT){
896                                                 FSWriteState = STATE_WRITE_PILOT_FAILED;
897                                         }
898 #endif
899                                 } else  if(inpacket.code == CMD_GAME_FREESPACE){
900 #ifndef MAKE_FS1
901                                         Int3();
902 #else
903                                         if(FSWriteState == STATE_SENDING_PILOT){
904                                                 FSWriteState = STATE_WRITE_PILOT_FAILED;
905                                         }
906 #endif
907                                 } else {
908                                         Int3();
909                                 }
910                                 break;
911
912                         case UNT_SW_RESULT_RESPONSE:
913                                 if(SWWriteState == STATE_SENDING_PILOT){                                        
914                                         // copy the data
915                                         SDL_assert((bytesin - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response));
916                                         if((bytesin - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response)){
917                                                 memset(&SquadWarWriteResponse, 0, sizeof(squad_war_response));
918                                                 memcpy(&SquadWarWriteResponse, inpacket.data, sizeof(squad_war_response));
919
920                                                 // now check to see if we're good
921                                                 if(SquadWarWriteResponse.accepted){
922                                                         SWWriteState = STATE_WROTE_PILOT;
923                                                 } else {
924                                                         SWWriteState = STATE_WRITE_PILOT_FAILED;
925                                                 }
926                                         } else {
927                                                 SWWriteState = STATE_WRITE_PILOT_FAILED;
928                                         }       
929                                 }
930                                 break;
931
932                         case UNT_CONTROL:
933                                 Int3();
934                                 break;
935
936                         case UNT_CONTROL_VALIDATION:
937                                 Int3();
938                                 break;
939
940                         default:
941                                 break;
942                         }
943                         AckServer(inpacket.sig);
944                 }
945         }
946 }