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