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