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