]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/valid.cpp
make gtrack compatible with FS1
[taylor/freespace2.git] / src / network / valid.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
11 //Validate tracker user class
12
13
14 #ifdef PLAT_UNIX
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
17 #include <errno.h>
18 #include <netdb.h>
19 #endif
20
21 #include "multi.h"
22 #include "ptrack.h"
23 #include "valid.h"
24 #include "psnet.h"
25 #include "timer.h"
26
27
28 // check structs for size compatibility
29 SDL_COMPILE_TIME_ASSERT(vmt_validate_mission_req_struct, sizeof(vmt_validate_mission_req_struct) == 104);
30
31
32 // Variables
33 udp_packet_header PacketHeader;
34 validate_id_request *ValidIDReq;
35
36 int ValidState;
37
38 #ifdef MAKE_FS1
39 SOCKET validsock;
40 #define VALIDSOCKET validsock
41 #else
42 #define VALIDSOCKET Unreliable_socket
43 #endif
44 struct sockaddr_in      rtrackaddr;
45
46 int ValidFirstSent;
47 int ValidLastSent;
48
49 char *Psztracker_id;
50
51 // mission validation
52 int MissionValidState;
53 int MissionValidFirstSent;
54 int MissionValidLastSent;
55
56 // squad war validation
57 int SquadWarValidState;
58 int SquadWarFirstSent;
59 int SquadWarLastSent;
60
61 // squad war response
62 squad_war_response SquadWarValidateResponse;
63
64
65 static int SerializeValidatePacket(const udp_packet_header *uph, ubyte *data)
66 {
67         int packet_size = 0;
68         int i;
69 #ifdef MAKE_FS1
70         char h_pad = 0;
71 #endif
72
73         PXO_ADD_DATA(uph->type);
74 #ifdef MAKE_FS1
75         PXO_ADD_DATA(h_pad);
76 #endif
77         PXO_ADD_USHORT(uph->len);
78         PXO_ADD_UINT(uph->code);
79         PXO_ADD_USHORT(uph->xcode);
80 #ifdef MAKE_FS1
81         PXO_ADD_DATA(h_pad);
82         PXO_ADD_DATA(h_pad);
83 #endif
84         PXO_ADD_UINT(uph->sig);
85         PXO_ADD_UINT(uph->security);
86
87         switch (uph->type) {
88                 // no extra data for this
89                 case UNT_CONTROL:
90                         break;
91
92                 case UNT_LOGIN_AUTH_REQUEST: {
93                         validate_id_request *id_req = (validate_id_request *)&uph->data;
94
95                         PXO_ADD_DATA(id_req->login);
96                         PXO_ADD_DATA(id_req->password);
97                         PXO_ADD_DATA(id_req->tracker_id);       // junk here, just for size
98
99                         break;
100                 }
101
102                 case UNT_VALID_FS2_MSN_REQ: {
103                         vmt_validate_mission_req_struct *mis_req = (vmt_validate_mission_req_struct *)&uph->data;
104
105                         PXO_ADD_UINT(mis_req->checksum);
106
107                         memcpy(data+packet_size, mis_req->file_name, strlen(mis_req->file_name));
108                         packet_size += strlen(mis_req->file_name);
109
110                         data[packet_size] = '\0';
111                         packet_size++;
112
113                         break;
114                 }
115
116                 case UNT_VALID_SW_MSN_REQ: {
117                         squad_war_request *sw_req = (squad_war_request *)&uph->data;
118
119                         for (i = 0; i < MAX_SQUAD_PLAYERS; i++) {
120                                 PXO_ADD_INT(sw_req->squad_plr1[i]);
121                         }
122
123                         for (i = 0; i < MAX_SQUAD_PLAYERS; i++) {
124                                 PXO_ADD_INT(sw_req->squad_plr2[i]);
125                         }
126
127                         PXO_ADD_DATA(sw_req->squad_count1);
128                         PXO_ADD_DATA(sw_req->squad_count2);
129
130                         PXO_ADD_DATA(sw_req->match_code);
131
132                         PXO_ADD_DATA(sw_req->mission_filename);
133                         PXO_ADD_INT(sw_req->mission_checksum);
134
135                         break;
136                 }
137
138                 // we shouldn't be sending any other packet types
139                 default:
140                         Int3();
141                         break;
142         }
143
144         SDL_assert(packet_size >= (int)PACKED_HEADER_ONLY_SIZE);
145         SDL_assert(packet_size == (int)uph->len);
146
147         return packet_size;
148 }
149
150 static void DeserializeValidatePacket(const ubyte *data, const int data_size, udp_packet_header *uph)
151 {
152         int offset = 0;
153 #ifdef MAKE_FS1
154         char h_pad;
155 #endif
156
157         memset(uph, 0, sizeof(udp_packet_header));
158
159         // make sure we received a complete base packet
160         if (data_size < (int)PACKED_HEADER_ONLY_SIZE) {
161                 uph->len = 0;
162                 uph->type = 0xff;
163
164                 return;
165         }
166
167         PXO_GET_DATA(uph->type);
168 #ifdef MAKE_FS1
169         PXO_GET_DATA(h_pad);
170 #endif
171         PXO_GET_USHORT(uph->len);
172         PXO_GET_UINT(uph->code);
173         PXO_GET_USHORT(uph->xcode);
174 #ifdef MAKE_FS1
175         PXO_GET_DATA(h_pad);
176         PXO_GET_DATA(h_pad);
177 #endif
178         PXO_GET_UINT(uph->sig);
179         PXO_GET_UINT(uph->security);
180
181         // sanity check data size to make sure we reveived all of the expected packet
182 #ifndef MAKE_FS1
183         // (the -1 is because psnet2 pops off one byte)
184         if ((int)uph->len-1 > data_size) {
185 #else
186         if ((int)uph->len > data_size) {
187 #endif
188                 uph->len = 0;
189                 uph->type = 0xff;
190
191                 return;
192         }
193
194         switch (uph->type) {
195                 // no extra data for these
196                 case UNT_CONTROL:
197                 case UNT_CONTROL_VALIDATION:
198                 case UNT_LOGIN_NO_AUTH:
199                 case UNT_VALID_FS_MSN_RSP:
200                 case UNT_VALID_FS2_MSN_RSP:
201                         break;
202
203                 case UNT_LOGIN_AUTHENTICATED: {
204                         SDL_strlcpy((char *)uph->data, (const char *)(data+offset), SDL_arraysize(uph->data));
205                         break;
206                 }
207
208                 case UNT_VALID_SW_MSN_RSP: {
209                         squad_war_response *sw_resp = (squad_war_response *)&uph->data;
210
211                         PXO_GET_DATA(sw_resp->reason);
212                         PXO_GET_DATA(sw_resp->accepted);
213
214                         break;
215                 }
216
217                 default:
218                         break;
219         }
220
221         //SDL_assert(offset == data_size);
222 }
223
224
225 int InitValidateClient(void)
226 {
227         struct sockaddr_in sockaddr;
228         in_addr_t iaddr;
229         ValidFirstSent = 0;
230         ValidLastSent = 0;
231         ValidState = VALID_STATE_IDLE;
232         
233         MissionValidFirstSent = 0;
234         MissionValidLastSent = 0;
235         MissionValidState = VALID_STATE_IDLE;
236
237         SquadWarFirstSent = 0;
238         SquadWarLastSent = 0;
239         SquadWarValidState = VALID_STATE_IDLE;
240
241 #ifdef MAKE_FS1
242         validsock = socket(AF_INET,SOCK_DGRAM,0);       
243         if ( validsock == (SOCKET)INVALID_SOCKET )
244         {
245                 mprintf(("Unable to open a socket.\n"));
246                 return 0;
247         }
248 #endif
249         
250         memset( &sockaddr, 0, sizeof(struct sockaddr_in) );
251         sockaddr.sin_family = AF_INET; 
252         sockaddr.sin_addr.s_addr = INADDR_ANY; 
253         sockaddr.sin_port = 0;
254         
255 #ifdef MAKE_FS1
256         if (SOCKET_ERROR==bind(validsock, (struct sockaddr*)&sockaddr, sizeof (sockaddr)))
257         {       
258                 mprintf(("Unable to bind a socket.\n"));
259                 mprintf(("WSAGetLastError() returned %d.\n",WSAGetLastError()));
260                 return 0;
261         }
262 #endif
263
264         rtrackaddr.sin_family = AF_INET; 
265         iaddr = inet_addr( Multi_options_g.user_tracker_ip );
266         if ( iaddr == INADDR_NONE ) {
267                 struct hostent *he;
268                 he = gethostbyname( Multi_options_g.user_tracker_ip );
269                 if(!he)
270                         return 0;
271         /*
272                 {               
273                         // try and resolve by address
274                         unsigned int n_order = inet_addr(Multi_user_tracker_ip_address);
275                         he = gethostbyaddr((char*)&n_order,4,PF_INET);
276
277                         if(!he){
278                                 return 0;
279                         }
280                 }
281         */
282                 iaddr = ((in_addr *)(he->h_addr))->s_addr;
283         }
284         
285         rtrackaddr.sin_addr.s_addr = iaddr;
286         rtrackaddr.sin_port = htons(REGPORT);
287         
288         return 1;
289
290 }
291
292 //Call with a valid struct to validate a user
293 //Call with NULL to poll
294
295 //Return codes:
296 // -3   Still waiting (returned if we were waiting for a tracker response and ValidateUser was called with a non-NULL value
297 // -2 Timeout waiting for tracker to respond
298 // -1   User invalid
299 //  0   Still waiting for response from tracker/Idle
300 //  1   User valid
301 int ValidateUser(validate_id_request *valid_id, char *trackerid)
302 {
303         ubyte packet_data[sizeof(udp_packet_header)];
304         int packet_length = 0;
305
306         ValidIdle();
307         if(valid_id==NULL)
308         {
309                 switch(ValidState)
310                 {
311                 case VALID_STATE_IDLE:
312                         return 0;
313                         break;
314                 case VALID_STATE_WAITING:
315                         return 0;
316                         break;
317                 case VALID_STATE_VALID:
318                         ValidState = VALID_STATE_IDLE;
319                         return 1;
320                         break;
321                 case VALID_STATE_INVALID:
322                         ValidState = VALID_STATE_IDLE;
323                         return -1;
324                 case VALID_STATE_TIMEOUT:
325                         ValidState = VALID_STATE_IDLE;
326                         return -2;
327                 }
328                 return 0;
329         }
330         else
331         {
332                 if(ValidState==VALID_STATE_IDLE)
333                 {
334                         //First, flush the input buffer for the socket
335                         fd_set read_fds;                   
336                         struct timeval timeout;
337                         
338                         timeout.tv_sec=0;            
339                         timeout.tv_usec=0;
340                         
341                         FD_ZERO(&read_fds);
342                         FD_SET(VALIDSOCKET, &read_fds);
343
344                         while(PXO_SELECT(VALIDSOCKET+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION))
345                         {
346                                 int addrsize;
347                                 struct sockaddr_in fromaddr;
348
349                                 udp_packet_header inpacket;
350                                 addrsize = sizeof(struct sockaddr_in);
351                                 PXO_RECVFROM(VALIDSOCKET, (char *)&inpacket,sizeof(udp_packet_header),0,(struct sockaddr *)&fromaddr,&addrsize, PSNET_TYPE_VALIDATION);
352                         }
353                         Psztracker_id = trackerid;
354
355                         //Build the request packet
356                         PacketHeader.type = UNT_LOGIN_AUTH_REQUEST;
357                         PacketHeader.len = PACKED_HEADER_ONLY_SIZE+sizeof(validate_id_request);
358                         ValidIDReq=(validate_id_request *)&PacketHeader.data;
359                         SDL_strlcpy(ValidIDReq->login, valid_id->login, SDL_arraysize(ValidIDReq->login));
360                         SDL_strlcpy(ValidIDReq->password, valid_id->password, SDL_arraysize(ValidIDReq->password));
361
362                         packet_length = SerializeValidatePacket(&PacketHeader, packet_data);
363                         PXO_SENDTO(VALIDSOCKET, (char *)&packet_data, packet_length, 0, (struct sockaddr *)&rtrackaddr, sizeof(struct sockaddr), PSNET_TYPE_VALIDATION);
364                         ValidState = VALID_STATE_WAITING;
365                         ValidFirstSent = timer_get_milliseconds();
366                         ValidLastSent = timer_get_milliseconds();
367                         return 0;
368                 }
369                 else
370                 {
371                         return -3;
372                 }
373         }
374 }
375
376
377 void ValidIdle()
378 {
379         fd_set read_fds;                   
380         struct timeval timeout;
381         ubyte packet_data[sizeof(udp_packet_header)];
382         int packet_length = 0;
383
384 #ifndef MAKE_FS1
385         PSNET_TOP_LAYER_PROCESS();
386 #endif
387
388         timeout.tv_sec=0;            
389         timeout.tv_usec=0;
390         
391         FD_ZERO(&read_fds);
392         FD_SET(VALIDSOCKET, &read_fds);
393
394         if(PXO_SELECT(VALIDSOCKET+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION)){
395                 int bytesin;
396                 int addrsize;
397                 struct sockaddr_in fromaddr;
398
399                 udp_packet_header inpacket;
400
401                 SDL_zero(inpacket);
402                 addrsize = sizeof(struct sockaddr_in);
403
404                 bytesin = PXO_RECVFROM(VALIDSOCKET, (char *)&packet_data, sizeof(udp_packet_header), 0, (struct sockaddr *)&fromaddr, &addrsize, PSNET_TYPE_VALIDATION);
405
406                 if (bytesin > 0) {
407                         DeserializeValidatePacket(packet_data, bytesin, &inpacket);
408
409 #ifndef MAKE_FS1
410                         // decrease packet size by 1
411                         inpacket.len--;
412 #endif
413 #ifndef NDEBUG
414                 } else {
415                         int wserr=WSAGetLastError();
416                         mprintf(("recvfrom() failure. WSAGetLastError() returned %d\n",wserr));
417 #endif
418                 }
419
420                 FD_ZERO(&read_fds);
421                 FD_SET(VALIDSOCKET, &read_fds);    
422
423                 //Check to make sure the packets ok
424                 if ( (bytesin > 0) && (bytesin == inpacket.len) ) {
425                         switch(inpacket.type)
426                         {
427                                 case UNT_LOGIN_NO_AUTH:
428                                         if(ValidState == VALID_STATE_WAITING)
429                                         {
430                                                 ValidState = VALID_STATE_INVALID;                                               
431                                         }
432                                         break;
433                                 case UNT_LOGIN_AUTHENTICATED:
434                                         if(ValidState == VALID_STATE_WAITING)
435                                         {
436                                                 ValidState = VALID_STATE_VALID;
437                                                 SDL_strlcpy(Psztracker_id, (const char *)&inpacket.data, TRACKER_ID_LEN);
438                                         }
439                                         break;
440                                 // old - this is a Freespace 1 packet type
441                                 case UNT_VALID_FS_MSN_RSP:
442                                         Int3();
443                                         break;
444
445                                 // fs2 mission validation response
446                                 case UNT_VALID_FS2_MSN_RSP:
447                                         if(MissionValidState == VALID_STATE_WAITING){
448                                                 if(inpacket.code==2){
449                                                         MissionValidState = VALID_STATE_VALID;
450                                                 } else {
451                                                         MissionValidState = VALID_STATE_INVALID;
452                                                 }
453                                         }
454                                         break;
455
456                                 // fs2 squad war validation response
457                                 case UNT_VALID_SW_MSN_RSP:
458                                         if(SquadWarValidState == VALID_STATE_WAITING){
459                                                 // copy the data
460                                                 SDL_assert((bytesin - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response));
461                                                 if((bytesin - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response)){
462                                                         memset(&SquadWarValidateResponse, 0, sizeof(squad_war_response));
463                                                         memcpy(&SquadWarValidateResponse, inpacket.data, sizeof(squad_war_response));
464
465                                                         // now check to see if we're good
466                                                         if(SquadWarValidateResponse.accepted){
467                                                                 SquadWarValidState = VALID_STATE_VALID;
468                                                         } else {
469                                                                 SquadWarValidState = VALID_STATE_INVALID;
470                                                         }
471                                                 } else {
472                                                         SquadWarValidState = VALID_STATE_INVALID;
473                                                 }                                               
474                                         }
475                                         break;
476
477                                 case UNT_CONTROL_VALIDATION:
478                                         Int3();
479                                         break;
480
481                                 case UNT_CONTROL:
482                                         Int3();
483                                         break;
484                         }
485                         AckValidServer(inpacket.sig);
486                 }
487         }
488
489         if(ValidState == VALID_STATE_WAITING)
490         {
491                 if((timer_get_milliseconds()-ValidFirstSent)>=PILOT_REQ_TIMEOUT)
492                 {
493                         ValidState = VALID_STATE_TIMEOUT;
494
495                 }               
496                 else if((timer_get_milliseconds()-ValidLastSent)>=PILOT_REQ_RESEND_TIME)
497                 {
498                         //Send 'da packet
499                         packet_length = SerializeValidatePacket(&PacketHeader, packet_data);
500                         PXO_SENDTO(VALIDSOCKET, (char *)&packet_data, packet_length, 0, (struct sockaddr *)&rtrackaddr, sizeof(struct sockaddr), PSNET_TYPE_VALIDATION);
501                         ValidLastSent = timer_get_milliseconds();
502                 }
503         }
504 }
505
506
507 //Send an ACK to the server
508 void AckValidServer(unsigned int sig)
509 {
510         udp_packet_header ack_pack;
511         ubyte packet_data[sizeof(udp_packet_header)];
512         int packet_length = 0;
513
514         ack_pack.type = UNT_CONTROL;
515         ack_pack.sig = sig;
516         ack_pack.code = CMD_CLIENT_RECEIVED;
517         ack_pack.len = PACKED_HEADER_ONLY_SIZE;
518
519         packet_length = SerializeValidatePacket(&ack_pack, packet_data);
520         SDL_assert(packet_length == PACKED_HEADER_ONLY_SIZE);
521         PXO_SENDTO(VALIDSOCKET, (char *)&packet_data, packet_length, 0, (struct sockaddr *)&rtrackaddr, sizeof(struct sockaddr_in), PSNET_TYPE_VALIDATION);
522 }
523
524 // call with a valid struct to validate a mission
525 // call with NULL to poll
526
527 // Return codes:
528 // -3   Still waiting (returned if we were waiting for a tracker response and ValidateMission was called with a non-NULL value
529 // -2 Timeout waiting for tracker to respond
530 // -1   User invalid
531 //  0   Still waiting for response from tracker/Idle
532 //  1   User valid
533 int ValidateMission(vmt_validate_mission_req_struct *valid_msn)
534 {
535         ubyte packet_data[sizeof(udp_packet_header)];
536         int packet_length = 0;
537
538         ValidIdle();
539         if(valid_msn==NULL)
540         {
541                 switch(MissionValidState)
542                 {
543                 case VALID_STATE_IDLE:
544                         return 0;
545                         break;
546                 case VALID_STATE_WAITING:
547                         return 0;
548                         break;                  
549                 case VALID_STATE_VALID:
550                         MissionValidState = VALID_STATE_IDLE;
551                         return 1;
552                         break;
553                 case VALID_STATE_INVALID:
554                         MissionValidState = VALID_STATE_IDLE;
555                         return -1;
556                 case VALID_STATE_TIMEOUT:
557                         MissionValidState = VALID_STATE_IDLE;
558                         return -2;
559                 }
560                 return 0;
561         }
562         else
563         {
564                 if(MissionValidState==VALID_STATE_IDLE)
565                 {
566                         //First, flush the input buffer for the socket
567                         fd_set read_fds;                   
568                         struct timeval timeout;
569                         
570                         timeout.tv_sec=0;            
571                         timeout.tv_usec=0;
572                         
573                         FD_ZERO(&read_fds);
574                         FD_SET(VALIDSOCKET, &read_fds);
575
576                         while(PXO_SELECT(VALIDSOCKET+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION))
577                         {
578                                 int addrsize;
579                                 struct sockaddr_in fromaddr;
580
581                                 udp_packet_header inpacket;
582                                 addrsize = sizeof(struct sockaddr_in);
583                                 PXO_RECVFROM(VALIDSOCKET, (char *)&inpacket,sizeof(udp_packet_header),0,(struct sockaddr *)&fromaddr,&addrsize, PSNET_TYPE_VALIDATION);
584                                 FD_ZERO(&read_fds);
585                                 FD_SET(VALIDSOCKET, &read_fds);
586                         }
587                         //only send the header, the checksum and the string length plus the null
588                         PacketHeader.type = UNT_VALID_FS2_MSN_REQ;
589                         PacketHeader.len = (short)(PACKED_HEADER_ONLY_SIZE + sizeof(int)+1+strlen(valid_msn->file_name));
590                         memcpy(PacketHeader.data,valid_msn,PacketHeader.len-PACKED_HEADER_ONLY_SIZE);
591                         packet_length = SerializeValidatePacket(&PacketHeader, packet_data);
592                         PXO_SENDTO(VALIDSOCKET, (char *)&packet_data, packet_length, 0, (struct sockaddr *)&rtrackaddr, sizeof(struct sockaddr), PSNET_TYPE_VALIDATION);
593                         MissionValidState = VALID_STATE_WAITING;
594                         MissionValidFirstSent = timer_get_milliseconds();
595                         MissionValidLastSent = timer_get_milliseconds();
596                         return 0;
597                 }
598                 else
599                 {
600                         return -3;
601                 }
602         }
603 }
604
605 // query the usertracker to validate a squad war match
606 // call with a valid struct to validate a mission
607 // call with NULL to poll
608
609 // Return codes:
610 // -3   Still waiting (returned if we were waiting for a tracker response and ValidateSquadWae was called with a non-NULL value
611 // -2 Timeout waiting for tracker to respond
612 // -1   match invalid
613 //  0   Still waiting for response from tracker/Idle
614 //  1   match valid
615 int ValidateSquadWar(squad_war_request *sw_req, squad_war_response *sw_resp)
616 {
617         ubyte packet_data[sizeof(udp_packet_header)];
618         int packet_length = 0;
619
620         ValidIdle();
621         if(sw_req==NULL){
622                 switch(SquadWarValidState){
623                 case VALID_STATE_IDLE:
624                         return 0;
625                         break;
626                 case VALID_STATE_WAITING:
627                         return 0;
628                         break;
629
630                 // fill in the response
631                 case VALID_STATE_VALID:
632                         SquadWarValidState = VALID_STATE_IDLE;
633                         if(sw_resp != NULL){
634                                 memcpy(sw_resp, &SquadWarValidateResponse, sizeof(squad_war_response));
635                         }
636                         return 1;
637                         break;
638                 // fill in the response
639                 case VALID_STATE_INVALID:
640                         SquadWarValidState = VALID_STATE_IDLE;
641                         if(sw_resp != NULL){
642                                 memcpy(sw_resp, &SquadWarValidateResponse, sizeof(squad_war_response));
643                         }
644                         return -1;
645
646                 case VALID_STATE_TIMEOUT:
647                         SquadWarValidState = VALID_STATE_IDLE;
648                         return -2;
649                 }
650                 return 0;
651         } else {
652                 if(SquadWarValidState==VALID_STATE_IDLE){
653                         // First, flush the input buffer for the socket
654                         fd_set read_fds;                   
655                         struct timeval timeout;
656                         
657                         timeout.tv_sec=0;            
658                         timeout.tv_usec=0;
659                         
660                         FD_ZERO(&read_fds);
661                         FD_SET(VALIDSOCKET, &read_fds);
662
663                         while(PXO_SELECT(VALIDSOCKET+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION)){
664                                 int addrsize;
665                                 struct sockaddr_in fromaddr;
666
667                                 udp_packet_header inpacket;
668                                 addrsize = sizeof(struct sockaddr_in);
669                                 PXO_RECVFROM(VALIDSOCKET, (char *)&inpacket,sizeof(udp_packet_header),0,(struct sockaddr *)&fromaddr,&addrsize, PSNET_TYPE_VALIDATION);
670                                 FD_ZERO(&read_fds);
671                                 FD_SET(VALIDSOCKET, &read_fds);
672                         }
673                         // only send the header, the checksum and the string length plus the null
674                         PacketHeader.type = UNT_VALID_SW_MSN_REQ;
675                         PacketHeader.len = (short)(PACKED_HEADER_ONLY_SIZE + sizeof(squad_war_request));
676                         memcpy(PacketHeader.data, sw_req, PacketHeader.len-PACKED_HEADER_ONLY_SIZE);
677                         packet_length = SerializeValidatePacket(&PacketHeader, packet_data);
678                         PXO_SENDTO(VALIDSOCKET, (char *)&packet_data, packet_length, 0, (struct sockaddr *)&rtrackaddr, sizeof(struct sockaddr), PSNET_TYPE_VALIDATION);
679                         SquadWarValidState = VALID_STATE_WAITING;
680                         SquadWarFirstSent = timer_get_milliseconds();
681                         SquadWarLastSent = timer_get_milliseconds();
682                         return 0;
683                 } else {
684                         return -3;
685                 }
686         }
687 }