client_connect.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:16k
- /*
- * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- #include "common/setup_before.h"
- #include <stdio.h>
- #ifdef STDC_HEADERS
- # include <stdlib.h>
- #endif
- #ifdef HAVE_MEMORY_H
- # include <memory.h>
- #endif
- #include "compat/memset.h"
- #include "compat/memcpy.h"
- #include <ctype.h>
- #ifdef HAVE_STRING_H
- # include <string.h>
- #endif
- #include <errno.h>
- #include "compat/strerror.h"
- #ifdef TIME_WITH_SYS_TIME
- # include <sys/time.h>
- # include <time.h>
- #else
- # ifdef HAVE_SYS_TIME_H
- # include <sys/time.h>
- # else
- # include <time.h>
- # endif
- #endif
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #endif
- #include "compat/gethostname.h"
- #ifdef HAVE_SYS_TYPES_H
- # include <sys/types.h>
- #endif
- #ifdef HAVE_SYS_SOCKET_H
- # include <sys/socket.h>
- #endif
- #include "compat/socket.h"
- #ifdef HAVE_SYS_PARAM_H
- # include <sys/param.h>
- #endif
- #ifdef HAVE_NETINET_IN_H
- # include <netinet/in.h>
- #endif
- #include "compat/netinet_in.h"
- #ifdef HAVE_ARPA_INET_H
- # include <arpa/inet.h>
- #endif
- #include "compat/inet_ntoa.h"
- #ifdef HAVE_NETDB_H
- # include <netdb.h>
- #endif
- #include "compat/psock.h"
- #include "common/packet.h"
- #include "common/init_protocol.h"
- #include "common/udp_protocol.h"
- #include "common/bnet_protocol.h"
- #include "common/file_protocol.h"
- #include "common/tag.h"
- #include "common/bn_type.h"
- #include "common/field_sizes.h"
- #include "common/bnethash.h"
- #include "common/bnethashconv.h"
- #include "common/util.h"
- #ifdef CLIENTDEBUG
- # include "common/eventlog.h"
- #endif
- #include "client.h"
- #include "udptest.h"
- #include "common/bnettime.h"
- #include "common/proginfo.h"
- #include "client_connect.h"
- #include "common/setup_after.h"
- #define COMPNAMELEN 128
- #ifdef CLIENTDEBUG
- # define dprintf printf
- #else
- # define dprintf if (0) printf
- #endif
- static int key_interpret(char const * cdkey, unsigned int * productid, unsigned int * keyvalue1, unsigned int * keyvalue2)
- {
- /* FIXME: implement... have example code from Eurijk! */
- *productid = 0;
- *keyvalue1 = 0;
- *keyvalue2 = 0;
- return 0;
- }
- static int get_defversioninfo(char const * progname, char const * clienttag, unsigned int * versionid, unsigned int * gameversion, char const * * exeinfo, unsigned int * checksum)
- {
- if (strcmp(clienttag,CLIENTTAG_DIABLORTL)==0)
- {
- *versionid = CLIENT_VERSIONID_DRTL;
- *gameversion = CLIENT_GAMEVERSION_DRTL;
- *exeinfo = CLIENT_EXEINFO_DRTL;
- *checksum = CLIENT_CHECKSUM_DRTL;
- return 0;
- }
-
- if (strcmp(clienttag,CLIENTTAG_STARCRAFT)==0)
- {
- *versionid = CLIENT_VERSIONID_STAR;
- *gameversion = CLIENT_GAMEVERSION_STAR;
- *exeinfo = CLIENT_EXEINFO_STAR;
- *checksum = CLIENT_CHECKSUM_STAR;
- return 0;
- }
-
- if (strcmp(clienttag,CLIENTTAG_SHAREWARE)==0)
- {
- *versionid = CLIENT_VERSIONID_SSHR;
- *gameversion = CLIENT_GAMEVERSION_SSHR;
- *exeinfo = CLIENT_EXEINFO_SSHR;
- *checksum = CLIENT_CHECKSUM_SSHR;
- return 0;
- }
-
- if (strcmp(clienttag,CLIENTTAG_BROODWARS)==0)
- {
- *versionid = CLIENT_VERSIONID_SEXP;
- *gameversion = CLIENT_GAMEVERSION_SEXP;
- *exeinfo = CLIENT_EXEINFO_SEXP;
- *checksum = CLIENT_CHECKSUM_SEXP;
- return 0;
- }
-
- if (strcmp(clienttag,CLIENTTAG_WARCIIBNE)==0)
- {
- *versionid = CLIENT_VERSIONID_W2BN;
- *gameversion = CLIENT_GAMEVERSION_W2BN;
- *exeinfo = CLIENT_EXEINFO_W2BN;
- *checksum = CLIENT_CHECKSUM_W2BN;
- return 0;
- }
-
- if (strcmp(clienttag,CLIENTTAG_DIABLO2DV)==0)
- {
- *versionid = CLIENT_VERSIONID_D2DV;
- *gameversion = CLIENT_GAMEVERSION_D2DV;
- *exeinfo = CLIENT_EXEINFO_D2DV;
- *checksum = CLIENT_CHECKSUM_D2DV;
- return 0;
- }
-
- if (strcmp(clienttag,CLIENTTAG_DIABLO2XP)==0)
- {
- *versionid = CLIENT_VERSIONID_D2XP;
- *gameversion = CLIENT_GAMEVERSION_D2XP;
- *exeinfo = CLIENT_EXEINFO_D2XP;
- *checksum = CLIENT_CHECKSUM_D2XP;
- return 0;
- }
-
- if (strcmp(clienttag,CLIENTTAG_WARCRAFT3)==0)
- {
- *versionid = CLIENT_VERSIONID_WAR3;
- *gameversion = CLIENT_GAMEVERSION_WAR3;
- *exeinfo = CLIENT_EXEINFO_WAR3;
- *checksum = CLIENT_CHECKSUM_WAR3;
- return 0;
- }
-
- *versionid = 0;
- *gameversion = 0;
- *exeinfo = "";
- *checksum = 0;
-
- fprintf(stderr,"%s: unsupported clienttag "%s"n",progname,clienttag);
- // aaron: dunno what we should return in case of this.. but returning nothing was definetly wrong
- return -1;
- }
- extern int client_connect(char const * progname, char const * servname, unsigned short servport, char const * cdowner, char const * cdkey, char const * clienttag, struct sockaddr_in * saddr, unsigned int * sessionkey, unsigned int * sessionnum, char const * archtag)
- {
- struct hostent * host;
- char const * username;
- int sd;
- t_packet * packet;
- t_packet * rpacket;
- char compname[COMPNAMELEN];
- int lsock;
- unsigned short lsock_port;
- unsigned int versionid;
- unsigned int gameversion;
- char const * exeinfo;
- unsigned int checksum;
-
- if (!progname)
- {
- fprintf(stderr,"got NULL prognamen");
- return -1;
- }
- if (!saddr)
- {
- fprintf(stderr,"%s: got NULL saddrn",progname);
- return -1;
- }
- if (!sessionkey)
- {
- fprintf(stderr,"%s: got NULL sessionkeyn",progname);
- return -1;
- }
- if (!sessionnum)
- {
- fprintf(stderr,"%s: got NULL sessionnumn",progname);
- return -1;
- }
-
- if (psock_init()<0)
- {
- fprintf(stderr,"%s: could not inialialize socket functionsn",progname);
- return -1;
- }
-
- if (!(host = gethostbyname(servname)))
- {
- fprintf(stderr,"%s: unknown host "%s"n",progname,servname);
- return -1;
- }
- if (host->h_addrtype!=PSOCK_AF_INET)
- fprintf(stderr,"%s: host "%s" is not in IPv4 address familyn",progname,servname);
-
- if (gethostname(compname,COMPNAMELEN)<0)
- {
- fprintf(stderr,"%s: could not get host name (gethostname: %s)n",progname,strerror(errno));
- return -1;
- }
- #ifdef HAVE_GETLOGIN
- if (!(username = getlogin()))
- #endif
- {
- username = "unknown";
- dprintf("%s: could not get login name, using "%s" (getlogin: %s)n",progname,username,strerror(errno));
- }
-
- if ((sd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0)
- {
- fprintf(stderr,"%s: could not create socket (psock_socket: %s)n",progname,strerror(psock_errno()));
- return -1;
- }
-
- memset(saddr,0,sizeof(*saddr));
- saddr->sin_family = PSOCK_AF_INET;
- saddr->sin_port = htons(servport);
- memcpy(&saddr->sin_addr.s_addr,host->h_addr_list[0],host->h_length);
- if (psock_connect(sd,(struct sockaddr *)saddr,sizeof(*saddr))<0)
- {
- fprintf(stderr,"%s: could not connect to server "%s" port %hu (psock_connect: %s)n",progname,servname,servport,strerror(psock_errno()));
- goto error_sd;
- }
-
- printf("Connected to %s:%hu.n",inet_ntoa(saddr->sin_addr),servport);
-
- #ifdef CLIENTDEBUG
- eventlog_set(stderr);
- #endif
-
- if ((lsock = client_udptest_setup(progname,&lsock_port))>=0)
- dprintf("Got UDP data on port %hun",lsock_port);
-
- if (!(packet = packet_create(packet_class_init)))
- {
- fprintf(stderr,"%s: could not create packetn",progname);
- goto error_lsock;
- }
- bn_byte_set(&packet->u.client_initconn.class,CLIENT_INITCONN_CLASS_DEFER); /* == bnet */
- client_blocksend_packet(sd,packet);
- packet_del_ref(packet);
-
- /* reuse this same packet over and over */
- if (!(rpacket = packet_create(packet_class_bnet)))
- {
- fprintf(stderr,"%s: could not create packetn",progname);
- goto error_lsock;
- }
-
- get_defversioninfo(progname,clienttag,&versionid,&gameversion,&exeinfo,&checksum);
- if (strcmp(clienttag,CLIENTTAG_DIABLOSHR)==0 ||
- strcmp(clienttag,CLIENTTAG_DIABLORTL)==0)
- {
- if (!(packet = packet_create(packet_class_bnet)))
- {
- fprintf(stderr,"%s: could not create packetn",progname);
- goto error_rpacket;
- }
- packet_set_size(packet,sizeof(t_client_unknown_1b));
- packet_set_type(packet,CLIENT_UNKNOWN_1B);
- bn_short_set(&packet->u.client_unknown_1b.unknown1,CLIENT_UNKNOWN_1B_UNKNOWN3);
- bn_short_nset(&packet->u.client_unknown_1b.port,lsock_port);
- bn_int_nset(&packet->u.client_unknown_1b.ip,0); /* FIXME */
- bn_int_set(&packet->u.client_unknown_1b.unknown2,CLIENT_UNKNOWN_1B_UNKNOWN3);
- bn_int_set(&packet->u.client_unknown_1b.unknown3,CLIENT_UNKNOWN_1B_UNKNOWN3);
- client_blocksend_packet(sd,packet);
- packet_del_ref(packet);
- }
-
- if (!(packet = packet_create(packet_class_bnet)))
- {
- fprintf(stderr,"%s: could not create packetn",progname);
- goto error_rpacket;
- }
- packet_set_size(packet,sizeof(t_client_countryinfo_109));
- packet_set_type(packet,CLIENT_COUNTRYINFO_109);
- bn_int_set(&packet->u.client_countryinfo_109.protocol,CLIENT_COUNTRYINFO_109_PROTOCOL);
- bn_int_tag_set(&packet->u.client_countryinfo_109.archtag,archtag);
- bn_int_tag_set(&packet->u.client_countryinfo_109.clienttag,clienttag);
- //AARON
- bn_int_set(&packet->u.client_countryinfo_109.versionid,versionid);
- bn_int_set(&packet->u.client_countryinfo_109.gamelang,CLIENT_COUNTRYINFO_109_GAMELANG);
- bn_int_set(&packet->u.client_countryinfo_109.localip,CLIENT_COUNTRYINFO_109_LOCALIP);
- {
- int bias;
-
- bias = local_tzbias();
-
- bn_int_set(&packet->u.client_countryinfo_109.bias,(unsigned int)bias); /* rely on 2's complement */
- dprintf("my tzbias = %d (0x%08hx)n",bias,(unsigned int)bias);
- }
- /* FIXME: determine from locale */
- bn_int_set(&packet->u.client_countryinfo_109.lcid,CLIENT_COUNTRYINFO_109_LANGID_USENGLISH);
- bn_int_set(&packet->u.client_countryinfo_109.langid,CLIENT_COUNTRYINFO_109_LANGID_USENGLISH);
- packet_append_string(packet,CLIENT_COUNTRYINFO_109_LANGSTR_USENGLISH);
- /* FIXME: determine from locale+timezone... from domain name... nothing really would
- work. Maybe add some command-line options */
- packet_append_string(packet,CLIENT_COUNTRYINFO_109_COUNTRYNAME_USA);
- client_blocksend_packet(sd,packet);
- packet_del_ref(packet);
-
- do
- if (client_blockrecv_packet(sd,rpacket)<0)
- {
- fprintf(stderr,"%s: server closed connectionn",progname);
- goto error_rpacket;
- }
- while (packet_get_type(rpacket)!=SERVER_AUTHREQ_109 &&
- packet_get_type(rpacket)!=SERVER_AUTHREPLY_109);
-
- if (packet_get_type(rpacket)==SERVER_AUTHREQ_109) /* hmm... server wants to check the version number */
- {
- dprintf("Got AUTHREQ_109n");
- *sessionkey = bn_int_get(rpacket->u.server_authreq_109.sessionkey);
- *sessionnum = bn_int_get(rpacket->u.server_authreq_109.sessionnum);
- /* FIXME: also get filename and equation */
- if (!(packet = packet_create(packet_class_bnet)))
- {
- fprintf(stderr,"%s: could not create packetn",progname);
- goto error_rpacket;
- }
- packet_set_size(packet,sizeof(t_client_authreq_109));
- packet_set_type(packet,CLIENT_AUTHREQ_109);
- bn_int_set(&packet->u.client_authreq_109.ticks,time(NULL));
-
- {
- t_cdkey_info cdkey_info;
-
- bn_int_set(&packet->u.client_authreq_109.gameversion,gameversion);
- bn_int_set(&packet->u.client_authreq_109.cdkey_number,1); /* only one */
- memset(&cdkey_info,'0',sizeof(cdkey_info));
- packet_append_data(packet,&cdkey,sizeof(cdkey_info)); /* cdkey - bogus for now */
- packet_append_string(packet,exeinfo);
- packet_append_string(packet,cdowner);
- }
-
- bn_int_set(&packet->u.client_authreq_109.checksum,checksum);
- client_blocksend_packet(sd,packet);
- packet_del_ref(packet);
-
- /* now wait for reply */
- do
- if (client_blockrecv_packet(sd,rpacket)<0)
- {
- fprintf(stderr,"%s: server closed connectionn",progname);
- goto error_rpacket;
- }
- while (packet_get_type(rpacket)!=SERVER_AUTHREPLY_109);
- //FIXME: check if AUTHREPLY_109 is success or fail
- if (bn_int_get(rpacket->u.server_authreply_109.message)!=SERVER_AUTHREPLY_109_MESSAGE_OK)
- {
- fprintf(stderr,"AUTHREPLY_109 failed - closing connectionn");
- goto error_rpacket;
- }
- }
- else
- fprintf(stderr,"We didn't get a sessionkey, don't expect login to work!");
- dprintf("Got AUTHREPLY_109n");
-
- if (!(packet = packet_create(packet_class_bnet)))
- {
- fprintf(stderr,"%s: could not create packetn",progname);
- goto error_rpacket;
- }
- packet_set_size(packet,sizeof(t_client_iconreq));
- packet_set_type(packet,CLIENT_ICONREQ);
- client_blocksend_packet(sd,packet);
- packet_del_ref(packet);
-
- do
- if (client_blockrecv_packet(sd,rpacket)<0)
- {
- fprintf(stderr,"%s: server closed connectionn",progname);
- goto error_rpacket;
- }
- while (packet_get_type(rpacket)!=SERVER_ICONREPLY);
- dprintf("Got ICONREPLYn");
-
- if (strcmp(clienttag,CLIENTTAG_STARCRAFT)==0 ||
- strcmp(clienttag,CLIENTTAG_BROODWARS)==0 ||
- strcmp(clienttag,CLIENTTAG_WARCIIBNE)==0)
- {
- if (!(packet = packet_create(packet_class_bnet)))
- {
- fprintf(stderr,"%s: could not create packetn",progname);
- goto error_rpacket;
- }
- {
- struct
- {
- bn_int sessionkey;
- bn_int ticks;
- bn_int productid;
- bn_int keyvalue1;
- bn_int keyvalue2;
- } temp;
- t_hash key_hash;
- unsigned int ticks;
- unsigned int keyvalue1,keyvalue2,productid;
-
- if (key_interpret(cdkey,&productid,&keyvalue1,&keyvalue2)<0)
- {
- fprintf(stderr,"%s: specified key is not valid, sending junkn",progname);
- productid = 0;
- keyvalue1 = 0;
- keyvalue2 = 0;
- }
-
- ticks = 0; /* FIXME: what to use here? */
- bn_int_set(&temp.ticks,ticks);
- bn_int_set(&temp.sessionkey,*sessionkey);
- bn_int_set(&temp.productid,productid);
- bn_int_set(&temp.keyvalue1,keyvalue1);
- bn_int_set(&temp.keyvalue2,keyvalue2);
- bnet_hash(&key_hash,sizeof(temp),&temp);
-
- packet_set_size(packet,sizeof(t_client_cdkey2));
- packet_set_type(packet,CLIENT_CDKEY2);
- bn_int_set(&packet->u.client_cdkey2.spawn,CLIENT_CDKEY2_SPAWN_FALSE); /* FIXME: add option */
- bn_int_set(&packet->u.client_cdkey2.keylen,strlen(cdkey));
- bn_int_set(&packet->u.client_cdkey2.productid,productid);
- bn_int_set(&packet->u.client_cdkey2.keyvalue1,keyvalue1);
- bn_int_set(&packet->u.client_cdkey2.sessionkey,*sessionkey);
- bn_int_set(&packet->u.client_cdkey2.ticks,ticks);
- hash_to_bnhash((t_hash const *)&key_hash,packet->u.client_cdkey2.key_hash); /* avoid warning */
- packet_append_string(packet,cdowner);
- client_blocksend_packet(sd,packet);
- packet_del_ref(packet);
- }
- do
- if (client_blockrecv_packet(sd,rpacket)<0)
- {
- fprintf(stderr,"%s: server closed connectionn",progname);
- goto error_rpacket;
- }
- while (packet_get_type(rpacket)!=SERVER_CDKEYREPLY2);
- dprintf("Got CDKEYREPLY2 (%u)n",bn_int_get(rpacket->u.server_cdkeyreply2.message));
- }
-
- packet_destroy(rpacket);
- return sd;
-
- /* error cleanup */
-
- error_rpacket:
-
- packet_destroy(rpacket);
-
- error_lsock:
-
- if (lsock>=0)
- psock_close(lsock);
-
- error_sd:
-
- psock_close(sd);
-
- return -1;
- }