]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/valid.cpp
first pass at PXO reintegration
[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 // Variables
29 udp_packet_header PacketHeader;
30 validate_id_request *ValidIDReq;
31
32 int ValidState;
33
34 // SOCKET validsock;
35 SOCKADDR_IN     rtrackaddr;
36
37 int ValidFirstSent;
38 int ValidLastSent;
39
40 char *Psztracker_id;
41
42 // mission validation
43 int MissionValidState;
44 int MissionValidFirstSent;
45 int MissionValidLastSent;
46
47 // squad war validation
48 int SquadWarValidState;
49 int SquadWarFirstSent;
50 int SquadWarLastSent;
51
52 // squad war response
53 squad_war_response SquadWarValidateResponse;
54
55 int InitValidateClient(void)
56 {
57         SOCKADDR_IN sockaddr;
58         unsigned long iaddr;
59         ValidFirstSent = 0;
60         ValidLastSent = 0;
61         ValidState = VALID_STATE_IDLE;
62         
63         MissionValidFirstSent = 0;
64         MissionValidLastSent = 0;
65         MissionValidState = VALID_STATE_IDLE;
66
67         SquadWarFirstSent = 0;
68         SquadWarLastSent = 0;
69         SquadWarValidState = VALID_STATE_IDLE;
70
71         /*
72         validsock = socket(AF_INET,SOCK_DGRAM,0);       
73         if ( validsock == INVALID_SOCKET )
74         {
75                 printf("Unable to open a socket.\n");
76                 return 0;
77         }
78         */
79         
80         memset( &sockaddr, 0, sizeof(SOCKADDR_IN) );
81         sockaddr.sin_family = AF_INET; 
82         sockaddr.sin_addr.s_addr = INADDR_ANY; 
83         sockaddr.sin_port = 0;
84         
85         /*
86         if (SOCKET_ERROR==bind(validsock, (SOCKADDR*)&sockaddr, sizeof (sockaddr))) 
87         {       
88                 printf("Unable to bind a socket.\n");
89                 printf("WSAGetLastError() returned %d.\n",WSAGetLastError());
90                 return 0;
91         }
92         */
93
94         rtrackaddr.sin_family = AF_INET; 
95         iaddr = inet_addr( Multi_options_g.user_tracker_ip );
96         if ( iaddr == INADDR_NONE ) {
97                 HOSTENT *he;
98                 he = gethostbyname( Multi_options_g.user_tracker_ip );
99                 if(!he)
100                         return 0;
101         /*
102                 {               
103                         // try and resolve by address
104                         unsigned int n_order = inet_addr(Multi_user_tracker_ip_address);
105                         he = gethostbyaddr((char*)&n_order,4,PF_INET);
106
107                         if(!he){
108                                 return 0;
109                         }
110                 }
111         */
112                 memcpy(&iaddr, he->h_addr_list[0],4);
113         }
114         
115         memcpy(&rtrackaddr.sin_addr.s_addr, &iaddr, 4);
116         rtrackaddr.sin_port = htons(REGPORT);
117         
118         return 1;
119
120 }
121
122 //Call with a valid struct to validate a user
123 //Call with NULL to poll
124
125 //Return codes:
126 // -3   Still waiting (returned if we were waiting for a tracker response and ValidateUser was called with a non-NULL value
127 // -2 Timeout waiting for tracker to respond
128 // -1   User invalid
129 //  0   Still waiting for response from tracker/Idle
130 //  1   User valid
131 int ValidateUser(validate_id_request *valid_id, char *trackerid)
132 {       
133         ValidIdle();
134         if(valid_id==NULL)
135         {
136                 switch(ValidState)
137                 {
138                 case VALID_STATE_IDLE:
139                         return 0;
140                         break;
141                 case VALID_STATE_WAITING:
142                         return 0;
143                         break;
144                 case VALID_STATE_VALID:
145                         ValidState = VALID_STATE_IDLE;
146                         return 1;
147                         break;
148                 case VALID_STATE_INVALID:
149                         ValidState = VALID_STATE_IDLE;
150                         return -1;
151                 case VALID_STATE_TIMEOUT:
152                         ValidState = VALID_STATE_IDLE;
153                         return -2;
154                 }
155                 return 0;
156         }
157         else
158         {
159                 if(ValidState==VALID_STATE_IDLE)
160                 {
161                         //First, flush the input buffer for the socket
162                         fd_set read_fds;                   
163                         TIMEVAL timeout;   
164                         
165                         timeout.tv_sec=0;            
166                         timeout.tv_usec=0;
167                         
168                         FD_ZERO(&read_fds);
169                         FD_SET(Unreliable_socket, &read_fds);    
170
171 #ifndef PLAT_UNIX
172                         while(SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION))
173 #else
174                         while(SELECT(Unreliable_socket+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION))
175 #endif
176                         {
177                                 int addrsize;
178                                 SOCKADDR_IN fromaddr;
179
180                                 udp_packet_header inpacket;
181                                 addrsize = sizeof(SOCKADDR_IN);
182                                 RECVFROM(Unreliable_socket, (char *)&inpacket,sizeof(udp_packet_header),0,(SOCKADDR *)&fromaddr,&addrsize, PSNET_TYPE_VALIDATION);
183                         }
184                         Psztracker_id = trackerid;
185
186                         //Build the request packet
187                         PacketHeader.type = UNT_LOGIN_AUTH_REQUEST;
188                         PacketHeader.len = PACKED_HEADER_ONLY_SIZE+sizeof(validate_id_request);
189                         ValidIDReq=(validate_id_request *)&PacketHeader.data;
190                         strcpy(ValidIDReq->login,valid_id->login);
191                         strcpy(ValidIDReq->password,valid_id->password);
192
193                         SENDTO(Unreliable_socket, (char *)&PacketHeader,PacketHeader.len,0,(SOCKADDR *)&rtrackaddr,sizeof(SOCKADDR), PSNET_TYPE_VALIDATION);
194                         ValidState = VALID_STATE_WAITING;
195                         ValidFirstSent = timer_get_milliseconds();
196                         ValidLastSent = timer_get_milliseconds();
197                         return 0;
198                 }
199                 else
200                 {
201                         return -3;
202                 }
203         }
204 }
205
206
207 void ValidIdle()
208 {
209         fd_set read_fds;                   
210         TIMEVAL timeout;   
211
212         PSNET_TOP_LAYER_PROCESS();
213         
214         timeout.tv_sec=0;            
215         timeout.tv_usec=0;
216         
217         FD_ZERO(&read_fds);
218         FD_SET(Unreliable_socket, &read_fds);    
219
220 #ifndef PLAT_UNIX
221         if(SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION)){
222 #else
223         if(SELECT(Unreliable_socket+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION)){
224 #endif
225                 int bytesin;
226                 int addrsize;
227                 SOCKADDR_IN fromaddr;
228
229                 udp_packet_header inpacket;
230                 addrsize = sizeof(SOCKADDR_IN);
231
232                 bytesin = RECVFROM(Unreliable_socket, (char *)&inpacket, sizeof(udp_packet_header),0,(SOCKADDR *)&fromaddr,&addrsize, PSNET_TYPE_VALIDATION);
233                 if(bytesin==-1){
234                         int wserr=WSAGetLastError();
235                         printf("recvfrom() failure. WSAGetLastError() returned %d\n",wserr);
236                         
237                 }
238                 FD_ZERO(&read_fds);
239                 FD_SET(Unreliable_socket, &read_fds);    
240                 
241                 // decrease packet size by 1
242                 inpacket.len--;
243
244                 //Check to make sure the packets ok
245                 if(bytesin==inpacket.len){
246                         switch(inpacket.type)
247                         {
248                                 case UNT_LOGIN_NO_AUTH:
249                                         if(ValidState == VALID_STATE_WAITING)
250                                         {
251                                                 ValidState = VALID_STATE_INVALID;                                               
252                                         }
253                                         break;
254                                 case UNT_LOGIN_AUTHENTICATED:
255                                         if(ValidState == VALID_STATE_WAITING)
256                                         {
257                                                 ValidState = VALID_STATE_VALID;
258                                                 strncpy(Psztracker_id, (const char *)&inpacket.data, TRACKER_ID_LEN);
259                                         }
260                                         break;
261                                 // old - this is a Freespace 1 packet type
262                                 case UNT_VALID_FS_MSN_RSP:
263                                         Int3();
264                                         break;
265
266                                 // fs2 mission validation response
267                                 case UNT_VALID_FS2_MSN_RSP:
268                                         if(MissionValidState == VALID_STATE_WAITING){
269                                                 if(inpacket.code==2){
270                                                         MissionValidState = VALID_STATE_VALID;
271                                                 } else {
272                                                         MissionValidState = VALID_STATE_INVALID;
273                                                 }
274                                         }
275                                         break;
276
277                                 // fs2 squad war validation response
278                                 case UNT_VALID_SW_MSN_RSP:
279                                         if(SquadWarValidState == VALID_STATE_WAITING){
280                                                 // copy the data
281                                                 SDL_assert((bytesin - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response));
282                                                 if((bytesin - PACKED_HEADER_ONLY_SIZE) == sizeof(squad_war_response)){
283                                                         memset(&SquadWarValidateResponse, 0, sizeof(squad_war_response));
284                                                         memcpy(&SquadWarValidateResponse, inpacket.data, sizeof(squad_war_response));
285
286                                                         // now check to see if we're good
287                                                         if(SquadWarValidateResponse.accepted){
288                                                                 SquadWarValidState = VALID_STATE_VALID;
289                                                         } else {
290                                                                 SquadWarValidState = VALID_STATE_INVALID;
291                                                         }
292                                                 } else {
293                                                         SquadWarValidState = VALID_STATE_INVALID;
294                                                 }                                               
295                                         }
296                                         break;
297
298                                 case UNT_CONTROL_VALIDATION:
299                                         Int3();
300                                         break;
301
302                                 case UNT_CONTROL:
303                                         Int3();
304                                         break;
305                         }
306                         AckValidServer(inpacket.sig);
307                 }
308         }
309
310         if(ValidState == VALID_STATE_WAITING)
311         {
312                 if((timer_get_milliseconds()-ValidFirstSent)>=PILOT_REQ_TIMEOUT)
313                 {
314                         ValidState = VALID_STATE_TIMEOUT;
315
316                 }               
317                 else if((timer_get_milliseconds()-ValidLastSent)>=PILOT_REQ_RESEND_TIME)
318                 {
319                         //Send 'da packet
320                         SENDTO(Unreliable_socket, (char *)&PacketHeader, PacketHeader.len, 0, (SOCKADDR *)&rtrackaddr, sizeof(SOCKADDR), PSNET_TYPE_VALIDATION);
321                         ValidLastSent = timer_get_milliseconds();
322                 }
323         }
324 }
325
326
327 //Send an ACK to the server
328 void AckValidServer(unsigned int sig)
329 {
330         udp_packet_header ack_pack;
331
332         ack_pack.type = UNT_CONTROL;
333         ack_pack.sig = sig;
334         ack_pack.code = CMD_CLIENT_RECEIVED;
335         ack_pack.len = PACKED_HEADER_ONLY_SIZE;
336         
337         SENDTO(Unreliable_socket, (char *)&ack_pack,PACKED_HEADER_ONLY_SIZE,0,(SOCKADDR *)&rtrackaddr,sizeof(SOCKADDR_IN), PSNET_TYPE_VALIDATION);
338 }
339
340 // call with a valid struct to validate a mission
341 // call with NULL to poll
342
343 // Return codes:
344 // -3   Still waiting (returned if we were waiting for a tracker response and ValidateMission was called with a non-NULL value
345 // -2 Timeout waiting for tracker to respond
346 // -1   User invalid
347 //  0   Still waiting for response from tracker/Idle
348 //  1   User valid
349 int ValidateMission(vmt_validate_mission_req_struct *valid_msn)
350 {       
351         ValidIdle();
352         if(valid_msn==NULL)
353         {
354                 switch(MissionValidState)
355                 {
356                 case VALID_STATE_IDLE:
357                         return 0;
358                         break;
359                 case VALID_STATE_WAITING:
360                         return 0;
361                         break;                  
362                 case VALID_STATE_VALID:
363                         MissionValidState = VALID_STATE_IDLE;
364                         return 1;
365                         break;
366                 case VALID_STATE_INVALID:
367                         MissionValidState = VALID_STATE_IDLE;
368                         return -1;
369                 case VALID_STATE_TIMEOUT:
370                         MissionValidState = VALID_STATE_IDLE;
371                         return -2;
372                 }
373                 return 0;
374         }
375         else
376         {
377                 if(MissionValidState==VALID_STATE_IDLE)
378                 {
379                         //First, flush the input buffer for the socket
380                         fd_set read_fds;                   
381                         TIMEVAL timeout;   
382                         
383                         timeout.tv_sec=0;            
384                         timeout.tv_usec=0;
385                         
386                         FD_ZERO(&read_fds);
387                         FD_SET(Unreliable_socket, &read_fds);    
388
389 #ifndef PLAT_UNIX
390                         while(SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION))
391 #else
392                         while(SELECT(Unreliable_socket+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION))
393 #endif
394                         {
395                                 int addrsize;
396                                 SOCKADDR_IN fromaddr;
397
398                                 udp_packet_header inpacket;
399                                 addrsize = sizeof(SOCKADDR_IN);
400                                 RECVFROM(Unreliable_socket, (char *)&inpacket,sizeof(udp_packet_header),0,(SOCKADDR *)&fromaddr,&addrsize, PSNET_TYPE_VALIDATION);
401                                 FD_ZERO(&read_fds);
402                                 FD_SET(Unreliable_socket, &read_fds);    
403                         }
404                         //only send the header, the checksum and the string length plus the null
405                         PacketHeader.type = UNT_VALID_FS2_MSN_REQ;
406                         PacketHeader.len = (short)(PACKED_HEADER_ONLY_SIZE + sizeof(int)+1+strlen(valid_msn->file_name));
407                         memcpy(PacketHeader.data,valid_msn,PacketHeader.len-PACKED_HEADER_ONLY_SIZE);
408                         SENDTO(Unreliable_socket, (char *)&PacketHeader,PacketHeader.len,0,(SOCKADDR *)&rtrackaddr,sizeof(SOCKADDR), PSNET_TYPE_VALIDATION);
409                         MissionValidState = VALID_STATE_WAITING;
410                         MissionValidFirstSent = timer_get_milliseconds();
411                         MissionValidLastSent = timer_get_milliseconds();
412                         return 0;
413                 }
414                 else
415                 {
416                         return -3;
417                 }
418         }
419 }
420
421 // query the usertracker to validate a squad war match
422 // call with a valid struct to validate a mission
423 // call with NULL to poll
424
425 // Return codes:
426 // -3   Still waiting (returned if we were waiting for a tracker response and ValidateSquadWae was called with a non-NULL value
427 // -2 Timeout waiting for tracker to respond
428 // -1   match invalid
429 //  0   Still waiting for response from tracker/Idle
430 //  1   match valid
431 int ValidateSquadWar(squad_war_request *sw_req, squad_war_response *sw_resp)
432 {
433         ValidIdle();
434         if(sw_req==NULL){
435                 switch(SquadWarValidState){
436                 case VALID_STATE_IDLE:
437                         return 0;
438                         break;
439                 case VALID_STATE_WAITING:
440                         return 0;
441                         break;
442
443                 // fill in the response
444                 case VALID_STATE_VALID:
445                         SquadWarValidState = VALID_STATE_IDLE;
446                         if(sw_resp != NULL){
447                                 memcpy(sw_resp, &SquadWarValidateResponse, sizeof(squad_war_response));
448                         }
449                         return 1;
450                         break;
451                 // fill in the response
452                 case VALID_STATE_INVALID:
453                         SquadWarValidState = VALID_STATE_IDLE;
454                         if(sw_resp != NULL){
455                                 memcpy(sw_resp, &SquadWarValidateResponse, sizeof(squad_war_response));
456                         }
457                         return -1;
458
459                 case VALID_STATE_TIMEOUT:
460                         SquadWarValidState = VALID_STATE_IDLE;
461                         return -2;
462                 }
463                 return 0;
464         } else {
465                 if(SquadWarValidState==VALID_STATE_IDLE){
466                         // First, flush the input buffer for the socket
467                         fd_set read_fds;                   
468                         TIMEVAL timeout;   
469                         
470                         timeout.tv_sec=0;            
471                         timeout.tv_usec=0;
472                         
473                         FD_ZERO(&read_fds);
474                         FD_SET(Unreliable_socket, &read_fds);    
475
476 #ifndef PLAT_UNIX
477                         while(SELECT(0,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION)){
478 #else
479                         while(SELECT(Unreliable_socket+1,&read_fds,NULL,NULL,&timeout, PSNET_TYPE_VALIDATION)){
480 #endif
481                                 int addrsize;
482                                 SOCKADDR_IN fromaddr;
483
484                                 udp_packet_header inpacket;
485                                 addrsize = sizeof(SOCKADDR_IN);
486                                 RECVFROM(Unreliable_socket, (char *)&inpacket,sizeof(udp_packet_header),0,(SOCKADDR *)&fromaddr,&addrsize, PSNET_TYPE_VALIDATION);
487                                 FD_ZERO(&read_fds);
488                                 FD_SET(Unreliable_socket, &read_fds);    
489                         }
490                         // only send the header, the checksum and the string length plus the null
491                         PacketHeader.type = UNT_VALID_SW_MSN_REQ;
492                         PacketHeader.len = (short)(PACKED_HEADER_ONLY_SIZE + sizeof(squad_war_request));
493                         memcpy(PacketHeader.data, sw_req, PacketHeader.len-PACKED_HEADER_ONLY_SIZE);
494                         SENDTO(Unreliable_socket, (char *)&PacketHeader, PacketHeader.len, 0, (SOCKADDR *)&rtrackaddr, sizeof(SOCKADDR), PSNET_TYPE_VALIDATION);
495                         SquadWarValidState = VALID_STATE_WAITING;
496                         SquadWarFirstSent = timer_get_milliseconds();
497                         SquadWarLastSent = timer_get_milliseconds();
498                         return 0;
499                 } else {
500                         return -3;
501                 }
502         }
503 }