Пример #1
0
/**
 * Map-serv sent us all his users info, (aid and cid) so we can update online_char_db
 * @param fd: wich fd to parse from
 * @param id: wich map_serv id
 * @return : 0 not enough data received, 1 success
 */
int chmapif_parse_regmapuser(int fd, int id){
	if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2))
		return 0;
	{
		//TODO: When data mismatches memory, update guild/party online/offline states.
		DBMap* online_char_db = char_get_onlinedb();
		int i;

		map_server[id].users = RFIFOW(fd,4);
		online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown'
		for(i = 0; i < map_server[id].users; i++) {
			int aid = RFIFOL(fd,6+i*8);
			int cid = RFIFOL(fd,6+i*8+4);
			struct online_char_data* character = idb_ensure(online_char_db, aid, char_create_online_data);
			if( character->server > -1 && character->server != id )
			{
				ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n",
					character->account_id, character->char_id, character->server, id, aid, cid);
				mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
			}
			character->server = id;
			character->char_id = cid;
		}
		//If any chars remain in -2, they will be cleaned in the cleanup timer.
		RFIFOSKIP(fd,RFIFOW(fd,2));
	}
	return 1;
}
Пример #2
0
/**
 * This function is called when the map-serv initialise is chrif interface.
 * Map-serv sent us his map indexes so we can transfert a player from a map-serv to another when necessary
 * We reply by sending back the char_serv_wisp_name  fame list and
 * @param fd: wich fd to parse from
 * @param id: wich map_serv id
 * @return : 0 not enough data received, 1 success
 */
int chmapif_parse_getmapname(int fd, int id){
	int j = 0, i = 0;
	if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
		return 0;

	//Retain what map-index that map-serv contains
	memset(map_server[id].map, 0, sizeof(map_server[id].map));
	for(i = 4; i < RFIFOW(fd,2); i += 4) {
		map_server[id].map[j] = RFIFOW(fd,i);
		j++;
	}

	ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
				id, j, CONVIP(map_server[id].ip), map_server[id].port);
	ShowStatus("Map-server %d loading complete.\n", id);

	// send name for wisp to player
	WFIFOHEAD(fd, 3 + NAME_LENGTH);
	WFIFOW(fd,0) = 0x2afb;
	WFIFOB(fd,2) = 0; //0 succes, 1:failure
	memcpy(WFIFOP(fd,3), charserv_config.wisp_server_name, NAME_LENGTH);
	WFIFOSET(fd,3+NAME_LENGTH);

	chmapif_send_fame_list(fd); //Send fame list.

	{
		int x;
		if (j == 0) {
			ShowWarning("Map-server %d has NO maps.\n", id);
		} else {
			unsigned char buf[16384];
			// Transmitting maps information to the other map-servers
			WBUFW(buf,0) = 0x2b04;
			WBUFW(buf,2) = j * 4 + 10;
			WBUFL(buf,4) = htonl(map_server[id].ip);
			WBUFW(buf,8) = htons(map_server[id].port);
			memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4);
			chmapif_sendallwos(fd, buf, WBUFW(buf,2));
		}
		// Transmitting the maps of the other map-servers to the new map-server
		for(x = 0; x < ARRAYLENGTH(map_server); x++) {
			if (map_server[x].fd > 0 && x != id) {
				WFIFOHEAD(fd,10 +4*ARRAYLENGTH(map_server[x].map));
				WFIFOW(fd,0) = 0x2b04;
				WFIFOL(fd,4) = htonl(map_server[x].ip);
				WFIFOW(fd,8) = htons(map_server[x].port);
				j = 0;
				for(i = 0; i < ARRAYLENGTH(map_server[x].map); i++)
					if (map_server[x].map[i])
						WFIFOW(fd,10+(j++)*4) = map_server[x].map[i];
				if (j > 0) {
					WFIFOW(fd,2) = j * 4 + 10;
					WFIFOSET(fd,WFIFOW(fd,2));
				}
			}
		}
	}
	RFIFOSKIP(fd,RFIFOW(fd,2));
	return 1;
}
Пример #3
0
/**
 * This function is called when the map-serv initialise is chrif interface.
 * Map-serv sent us his map indexes so we can transfert a player from a map-serv to another when necessary
 * We reply by sending back the char_serv_wisp_name  fame list and
 * @param fd: wich fd to parse from
 * @param id: wich map_serv id
 * @return : 0 not enough data received, 1 success
 */
int chmapif_parse_getmapname(int fd, int id){
	int i = 0, j = 0;
	unsigned char *mapbuf;

	if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
		return 0;

	//Retain what map-index that map-serv contains
	memset(map_server[id].map, 0, sizeof(map_server[id].map));
	for(i = 4; i < RFIFOW(fd,2); i += 4) {
		map_server[id].map[j] = RFIFOW(fd,i);
		j++;
	}

	mapbuf = RFIFOP(fd,4);
	RFIFOSKIP(fd,RFIFOW(fd,2));

	ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
				id, j, CONVIP(map_server[id].ip), map_server[id].port);
	ShowStatus("Map-server %d loading complete.\n", id);

	chmapif_send_misc(fd);
	chmapif_send_fame_list(fd); //Send fame list.
	chmapif_send_maps(fd, id, j, mapbuf);

	return 1;
}
Пример #4
0
//Request to save skill cooldown data
int chmapif_parse_req_saveskillcooldown(int fd){
	if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
		return 0;
	else {
		int count, aid, cid;
		aid = RFIFOL(fd,4);
		cid = RFIFOL(fd,8);
		count = RFIFOW(fd,12);
		if( count > 0 )
		{
			struct skill_cooldown_data data;
			StringBuf buf;
			int i;

			StringBuf_Init(&buf);
			StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `skill`, `tick`) VALUES ", schema_config.skillcooldown_db);
			for( i = 0; i < count; ++i )
			{
				memcpy(&data,RFIFOP(fd,14+i*sizeof(struct skill_cooldown_data)),sizeof(struct skill_cooldown_data));
				if( i > 0 )
					StringBuf_AppendStr(&buf, ", ");
				StringBuf_Printf(&buf, "('%d','%d','%d','%d')", aid, cid, data.skill_id, data.tick);
			}
			if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
				Sql_ShowDebug(sql_handle);
			StringBuf_Destroy(&buf);
		}
		RFIFOSKIP(fd, RFIFOW(fd, 2));
	}
	return 1;
}
Пример #5
0
int chlogif_parse_ack_global_accreg(int fd, struct char_session_data* sd){
	if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
		return 0;
	else { //Receive account_reg2 registry, forward to map servers.
		RFIFOW(fd,0) = 0x3804;
		chmapif_sendall(RFIFOP(fd,0), RFIFOW(fd,2));
		RFIFOSKIP(fd, RFIFOW(fd,2));
	}
	return 1;
}
Пример #6
0
int chlogif_parse_ackacc2req(int fd, struct char_session_data* sd){
	if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
		return 0;

	{	//Receive account_reg2 registry, forward to map servers.
		unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)];
		memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2));
		WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex]
		chmapif_sendall(buf, WBUFW(buf,2));
		RFIFOSKIP(fd, RFIFOW(fd,2));
	}
	return 1;
}
Пример #7
0
// RFIFOのパケット長確認
// 必要パケット長があればパケット長、まだ足りなければ0
int inter_check_length(int fd,int length)
{
	if(length==-1){	// 可変パケット長
		if(RFIFOREST(fd)<4)	// パケット長が未着
			return 0;
		length = RFIFOW(fd,2);
	}
	
	if(RFIFOREST(fd)<length)	// パケットが未着
		return 0;
	
	return length;
}
Пример #8
0
// RFIFO check
int inter_check_length(int fd, int length)
{
	if(length==-1){	// v-len packet
		if(RFIFOREST(fd)<4)	// packet not yet
			return 0;
		length = RFIFOW(fd, 2);
	}

	if((int)RFIFOREST(fd) < length)	// packet not yet
		return 0;

	return length;
}
Пример #9
0
/// Returns the length of the next complete packet to process,
/// or 0 if no complete packet exists in the queue.
///
/// @param length The minimum allowed length, or -1 for dynamic lookup
int inter_check_length(int fd, int length)
{
	if( length == -1 )
	{// variable-length packet
		if( RFIFOREST(fd) < 4 )
			return 0;
		length = RFIFOW(fd,2);
	}

	if( (int)RFIFOREST(fd) < length )
		return 0;

	return length;
}
Пример #10
0
/**
 * Player requesting to change map-serv
 * @param fd: wich fd to parse from
 * @return : 0 not enough data received, 1 success
 */
int chmapif_parse_reqchangemapserv(int fd){
	if (RFIFOREST(fd) < 39)
		return 0;
	{
		int map_id, map_fd = -1;
		struct mmo_charstatus* char_data;
		struct mmo_charstatus char_dat;
		DBMap* char_db_ = char_get_chardb();

		map_id = char_search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
		if (map_id >= 0)
			map_fd = map_server[map_id].fd;
		//Char should just had been saved before this packet, so this should be safe. [Skotlex]
		char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
		if (char_data == NULL) {	//Really shouldn't happen.
			char_mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true);
			char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
		}

		if( runflag == CHARSERVER_ST_RUNNING &&
			session_isActive(map_fd) &&
			char_data )
		{	//Send the map server the auth of this player.
			struct online_char_data* data;
			struct auth_node* node;
			DBMap*  auth_db = char_get_authdb();
			DBMap* online_char_db = char_get_onlinedb();

			int aid = RFIFOL(fd,2);

			//Update the "last map" as this is where the player must be spawned on the new map server.
			char_data->last_point.map = RFIFOW(fd,18);
			char_data->last_point.x = RFIFOW(fd,20);
			char_data->last_point.y = RFIFOW(fd,22);
			char_data->sex = RFIFOB(fd,30);

			// create temporary auth entry
			CREATE(node, struct auth_node, 1);
			node->account_id = aid;
			node->char_id = RFIFOL(fd,14);
			node->login_id1 = RFIFOL(fd,6);
			node->login_id2 = RFIFOL(fd,10);
			node->sex = RFIFOB(fd,30);
			node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing)
			node->ip = ntohl(RFIFOL(fd,31));
			node->group_id = RFIFOL(fd,35);
			node->changing_mapservers = 1;
			idb_put(auth_db, aid, node);

			data = idb_ensure(online_char_db, aid, char_create_online_data);
			data->char_id = char_data->char_id;
			data->server = map_id; //Update server where char is.

			//Reply with an ack.
			chmapif_changemapserv_ack(fd,0);
		} else { //Reply with nak
			chmapif_changemapserv_ack(fd,1);
		}
		RFIFOSKIP(fd,39);
	}
Пример #11
0
int chlogif_parse_keepalive(int fd, struct char_session_data* sd){
	if (RFIFOREST(fd) < 2)
		return 0;
	RFIFOSKIP(fd,2);
	session[fd]->flag.ping = 0;
	return 1;
}
Пример #12
0
/// clean up by discarding handled bytes
inline
void RFIFOFLUSH(int fd)
{
    really_memmove(&session[fd]->rdata[0], &session[fd]->rdata[session[fd]->rdata_pos], RFIFOREST(fd));
    session[fd]->rdata_size = RFIFOREST(fd);
    session[fd]->rdata_pos = 0;
}
Пример #13
0
/*
 * Client request to change pincode
 */
int chclif_parse_pincode_change( int fd, struct char_session_data* sd ){
	if( RFIFOREST(fd) < 14 )
		return 0;
	if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id )
		return 1;
	else {
		char oldpin[PINCODE_LENGTH+1];
		char newpin[PINCODE_LENGTH+1];
		
		memset(oldpin,0,PINCODE_LENGTH+1);
		memset(newpin,0,PINCODE_LENGTH+1);
		strncpy(oldpin, RFIFOCP(fd,6), PINCODE_LENGTH);
		strncpy(newpin, RFIFOCP(fd,10), PINCODE_LENGTH);
		RFIFOSKIP(fd,14);
		
		char_pincode_decrypt(sd->pincode_seed,oldpin);
		if( !char_pincode_compare( fd, sd, oldpin ) )
			return 1;
		char_pincode_decrypt(sd->pincode_seed,newpin);

		if( pincode_allowed(newpin) ){
			chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin );
			strncpy(sd->pincode, newpin, sizeof(newpin));
			ShowInfo("Pincode changed for AID: %d\n", sd->account_id);
		
			chclif_pincode_sendstate( fd, sd, PINCODE_PASSED );
		}else{
			chclif_pincode_sendstate( fd, sd, PINCODE_ILLEGAL );
		}
	}
	return 1;
}
Пример #14
0
/**
 * Set account_id to offline.
 * @author  [Wizputer]
 * @param fd: fd to parse from (char-serv)
 * @return 0 not enough info transmitted, 1 success
 */
int logchrif_parse_setaccoffline(int fd){
	if( RFIFOREST(fd) < 6 )
		return 0;
	login_remove_online_user(RFIFOL(fd,2));
	RFIFOSKIP(fd,6);
	return 1;
}
Пример #15
0
/**
 * We receive account_reg2 from a char-server, and we send them to other char-servers.
 * @param fd: fd to parse from (char-serv)
 * @param id: id of char-serv
 * @param ip: char-serv ip (used for info)
 * @return 0 not enough info transmitted, 1 success
 */
int logchrif_parse_upd_global_accreg(int fd, int id, char* ip){
	if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
		return 0;
	else{
		struct mmo_account acc;
		AccountDB* accounts = login_get_accounts_db();
		uint32 account_id = RFIFOL(fd,4);

		if( !accounts->load_num(accounts, &acc, account_id) )
			ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
		else
			mmo_save_global_accreg(accounts,fd,account_id,RFIFOL(fd, 8));
		RFIFOSKIP(fd,RFIFOW(fd,2));
	}
	return 1;
}
Пример #16
0
/**
 * Set account_id to online.
 * @author [Wizputer]
 * @param fd: fd to parse from (char-serv)
 * @param id: id of char-serv
 * @return 0 not enough info transmitted, 1 success
 */
int logchrif_parse_setacconline(int fd, int id){
	if( RFIFOREST(fd) < 6 )
		return 0;
	login_add_online_user(id, RFIFOL(fd,2));
	RFIFOSKIP(fd,6);
	return 1;
}
Пример #17
0
/**
 * Map server send information to change an email of an account via char-server.
 * 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
 * @param fd: fd to parse from (char-serv)
 * @param id: id of char-serv
 * @param ip: char-serv ip (used for info)
 * @return 0 not enough info transmitted, 1 success
 */
int logchrif_parse_reqchangemail(int fd, int id, char* ip){
	if (RFIFOREST(fd) < 86)
		return 0;
	else{
		struct mmo_account acc;
		AccountDB* accounts = login_get_accounts_db();
		char actual_email[40];
		char new_email[40];

		uint32 account_id = RFIFOL(fd,2);
		safestrncpy(actual_email, RFIFOCP(fd,6), 40);
		safestrncpy(new_email, RFIFOCP(fd,46), 40);
		RFIFOSKIP(fd, 86);

		if( e_mail_check(actual_email) == 0 )
			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
		else if( e_mail_check(new_email) == 0 )
			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
		else if( strcmpi(new_email, "*****@*****.**") == 0 )
			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
		else if( !accounts->load_num(accounts, &acc, account_id) )
			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
		else if( strcmpi(acc.email, actual_email) != 0 )
			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, acc.email, actual_email, ip);
		else{
			safestrncpy(acc.email, new_email, 40);
			ShowNotice("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, new_email, ip);
			// Save
			accounts->save(accounts, &acc);
		}
	}
	return 1;
}
Пример #18
0
/**
 * Receiving a sex change request (sex is reversed).
 * @param fd: fd to parse from (char-serv)
 * @param id: id of char-serv
 * @param ip: char-serv ip (used for info)
 * @return 0 not enough info transmitted, 1 success
 */
int logchrif_parse_reqchgsex(int fd, int id, char* ip){
	if( RFIFOREST(fd) < 6 )
		return 0;
	else{
		struct mmo_account acc;
		AccountDB* accounts = login_get_accounts_db();

		uint32 account_id = RFIFOL(fd,2);
		RFIFOSKIP(fd,6);

		if( !accounts->load_num(accounts, &acc, account_id) )
			ShowNotice("Char-server '%s': Error of sex change (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
		else if( acc.sex == 'S' )
			ShowNotice("Char-server '%s': Error of sex change - account to change is a Server account (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
		else{
			unsigned char buf[7];
			char sex = ( acc.sex == 'M' ) ? 'F' : 'M'; //Change gender

			ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", ch_server[id].name, account_id, sex, ip);

			acc.sex = sex;
			// Save
			accounts->save(accounts, &acc);

			// announce to other servers
			WBUFW(buf,0) = 0x2723;
			WBUFL(buf,2) = account_id;
			WBUFB(buf,6) = sex_str2num(sex);
			logchrif_sendallwos(-1, buf, 7);
		}
	}
	return 1;
}
Пример #19
0
int chlogif_parse_askkick(int fd, struct char_session_data* sd){
	if (RFIFOREST(fd) < 6)
		return 0;
	else {
		DBMap*  online_char_db = char_get_onlinedb();
		DBMap*  auth_db = char_get_authdb();
		int aid = RFIFOL(fd,2);
		struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid);
		RFIFOSKIP(fd,6);
		if( character != NULL )
		{// account is already marked as online!
			if( character->server > -1 )
			{	//Kick it from the map server it is on.
				mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
				if (character->waiting_disconnect == INVALID_TIMER)
					character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, char_chardb_waiting_disconnect, character->account_id, 0);
			}
			else
			{// Manual kick from char server.
				struct char_session_data *tsd;
				int i;
				ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid );
				if( i < fd_max )
				{
					chclif_send_auth_result(i,2);  //Send "Someone has already logged in with this id"
					set_eof(i);
				}
				else // still moving to the map-server
					char_set_char_offline(-1, aid);
			}
		}
		idb_remove(auth_db, aid);// reject auth attempts from map-server
	}
	return 1;
}
Пример #20
0
int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd){
	if (RFIFOREST(fd) < 21)
		return 0;
	{
		uint32 account_id = RFIFOL(fd,2);
		uint32 login_id1 = RFIFOL(fd,6);
		uint32 login_id2 = RFIFOL(fd,10);
		uint8 sex = RFIFOB(fd,14);
		uint8 result = RFIFOB(fd,15);
		int request_id = RFIFOL(fd,16);
		uint8 clienttype = RFIFOB(fd,20);
		RFIFOSKIP(fd,21);

		if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) &&
			!sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex )
		{
			int client_fd = request_id;
			sd->clienttype = clienttype;

			switch( result )
			{
			case 0:// ok
				char_auth_ok(client_fd, sd);
				break;
			case 1:// auth failed
				chclif_reject(client_fd,0); // rejected from server
				break;
			}
		}
	}
	return 1;
}
Пример #21
0
int chlogif_parse(int fd) {
	struct char_session_data* sd = NULL;

	// only process data from the login-server
	if( fd != login_fd ) {
		ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
		do_close(fd);
		return 0;
	}

	if( session[fd]->flag.eof ) {
		do_close(fd);
		login_fd = -1;
		chlogif_on_disconnect();
		return 0;
	} else if ( session[fd]->flag.ping ) {/* we've reached stall time */
		if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */
			set_eof(fd);
			return 0;
		} else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */
			WFIFOHEAD(fd,2);// sends a ping packet to login server (will receive pong 0x2718)
			WFIFOW(fd,0) = 0x2719;
			WFIFOSET(fd,2);

			session[fd]->flag.ping = 2;
		}
	}

	sd = (struct char_session_data*)session[fd]->session_data;

	while(RFIFOREST(fd) >= 2) {
		// -1: Login server is not connected
		//  0: Avoid processing followup packets (prev was probably incomplete) packet
		//  1: Continue parsing
		int next = 1;
		uint16 command = RFIFOW(fd,0);
		switch( command ) {
			case 0x2711: next = chlogif_parse_ackconnect(fd,sd); break;
			case 0x2713: next = chlogif_parse_ackaccreq(fd, sd); break;
			case 0x2717: next = chlogif_parse_reqaccdata(fd, sd); break;
			case 0x2718: next = chlogif_parse_keepalive(fd, sd); break;
			case 0x2721: next = chlogif_parse_AccInfoAck(fd); break;
			case 0x2723: next = chlogif_parse_ackchangesex(fd, sd); break;
			case 0x2726: next = chlogif_parse_ack_global_accreg(fd, sd); break;
			case 0x2731: next = chlogif_parse_accbannotification(fd, sd); break;
			case 0x2734: next = chlogif_parse_askkick(fd,sd); break;
			case 0x2735: next = chlogif_parse_updip(fd,sd); break;
			case 0x2743: next = chlogif_parse_vipack(fd); break;
			default:
				ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command);
				set_eof(fd);
				return 0;
		}
		if (next == 0)
			return 0; //do not parse next data
	}

	RFIFOFLUSH(fd);
	return 0;
}
Пример #22
0
/*
 * activate PIN system and set first PIN
 */
int chclif_parse_pincode_setnew( int fd, struct char_session_data* sd ){
	if( RFIFOREST(fd) < 10 )
		return 0;

	if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id )
		return 1;
	else {
		char newpin[PINCODE_LENGTH+1];
		memset(newpin,0,PINCODE_LENGTH+1);
		strncpy( newpin, RFIFOCP(fd,6), PINCODE_LENGTH );
		RFIFOSKIP(fd,10);

		char_pincode_decrypt( sd->pincode_seed, newpin );

		if( pincode_allowed(newpin) ){
			chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin );
			strncpy( sd->pincode, newpin, strlen( newpin ) );

			chclif_pincode_sendstate( fd, sd, PINCODE_PASSED );	
		}else{
			chclif_pincode_sendstate( fd, sd, PINCODE_ILLEGAL );
		}
	}
	return 1;
}
Пример #23
0
/**
 * Entry point from char-server to log-server.
 * Function that checks incoming command, then splits it to the correct handler.
 * @param fd: file descriptor to parse, (link to char-serv)
 * @return 0=invalid server,marked for disconnection,unknow packet; 1=success
 */
int logchrif_parse(int fd){
	int cid; //char-serv id
	uint32 ipl;
	char ip[16];

	ARR_FIND( 0, ARRAYLENGTH(ch_server), cid, ch_server[cid].fd == fd );
	if( cid == ARRAYLENGTH(ch_server) ){// not a char server
		ShowDebug("logchrif_parse: Disconnecting invalid session #%d (is not a char-server)\n", fd);
		set_eof(fd);
		do_close(fd);
		return 0;
	}

	if( session[fd]->flag.eof ){
		do_close(fd);
		ch_server[cid].fd = -1;
		logchrif_on_disconnect(cid);
		return 0;
	}

	ipl = ch_server[cid].ip;
	ip2str(ipl, ip);

	while( RFIFOREST(fd) >= 2 ){
		int next = 1; // 0: avoid processing followup packets (prev was probably incomplete) packet, 1: Continue parsing
		uint16 command = RFIFOW(fd,0);
		switch( command ){
			case 0x2712: next = logchrif_parse_reqauth(fd, cid, ip); break;
			case 0x2714: next = logchrif_parse_ackusercount(fd, cid); break;
			case 0x2716: next = logchrif_parse_reqaccdata(fd, cid, ip); break;
			case 0x2719: next = logchrif_parse_keepalive(fd); break;
			case 0x2720: next = logchrif_parse_accinfo(fd); break; //@accinfo from inter-server
			case 0x2722: next = logchrif_parse_reqchangemail(fd,cid,ip); break;
			case 0x2724: next = logchrif_parse_requpdaccstate(fd,cid,ip); break;
			case 0x2725: next = logchrif_parse_reqbanacc(fd,cid,ip); break;
			case 0x2727: next = logchrif_parse_reqchgsex(fd,cid,ip); break;
			case 0x2728: next = logchrif_parse_upd_global_accreg(fd,cid,ip); break;
			case 0x272a: next = logchrif_parse_requnbanacc(fd,cid,ip); break;
			case 0x272b: next = logchrif_parse_setacconline(fd,cid); break;
			case 0x272c: next = logchrif_parse_setaccoffline(fd); break;
			case 0x272d: next = logchrif_parse_updonlinedb(fd,cid); break;
			case 0x272e: next = logchrif_parse_req_global_accreg(fd); break;
			case 0x2736: next = logchrif_parse_updcharip(fd,cid); break;
			case 0x2737: next = logchrif_parse_setalloffline(fd,cid); break;
#if PACKETVER_SUPPORTS_PINCODE
			case 0x2738: next = logchrif_parse_updpincode(fd); break;
			case 0x2739: next = logchrif_parse_pincode_authfail(fd); break;
#endif
			case 0x2742: next = logchrif_parse_reqvipdata(fd); break; //Vip sys
			default:
				ShowError("logchrif_parse: Unknown packet 0x%x from a char-server! Disconnecting!\n", command);
				set_eof(fd);
				return 0;
		} // switch
		if (next == 0)
			return 0;
	} // while
	return 1; //or 0
}
Пример #24
0
/**
 * Received new charip from char-serv, update information.
 * @param fd: char-serv file descriptor
 * @param id: char-serv id
 * @return 0 not enough info transmitted, 1 success
 */
int logchrif_parse_updcharip(int fd, int id){
	if( RFIFOREST(fd) < 6 )
		return 0;
	ch_server[id].ip = ntohl(RFIFOL(fd,2));
	ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(ch_server[id].ip));
	RFIFOSKIP(fd,6);
	return 1;
}
Пример #25
0
/**
 * Received a keepalive packet to maintain connection.
 * S 0204 <md5 hash>.16B (kRO 2004-05-31aSakexe langtype 0 and 6)
 * @param fd: fd to parse from (client fd)
 * @return 0 not enough info transmitted, 1 success
 */
static int logclif_parse_updclhash(int fd, struct login_session_data *sd){
	if (RFIFOREST(fd) < 18)
		return 0;
	sd->has_client_hash = 1;
	memcpy(sd->client_hash, RFIFOP(fd, 2), 16);
	RFIFOSKIP(fd,18);
	return 1;
}
Пример #26
0
/*
 * Client is requesting to move a charslot
 */
int chclif_parse_moveCharSlot( int fd, struct char_session_data* sd){
	uint16 from, to;

	if( RFIFOREST(fd) < 8 )
		return 0;
	from = RFIFOW(fd,2);
	to = RFIFOW(fd,4);
	//Cnt = RFIFOW(fd,6); //how many time we have left to change (client.. lol we don't trust him)
	RFIFOSKIP(fd,8);

	// Have we changed to often or is it disabled?
	if( (charserv_config.charmove_config.char_move_enabled)==0
	|| ( (charserv_config.charmove_config.char_moves_unlimited)==0 && sd->char_moves[from] <= 0 ) ){
		chclif_moveCharSlotReply( fd, sd, from, 1 );
		return 1;
	}

	// We don't even have a character on the chosen slot?
	if( sd->found_char[from] <= 0 || to >= sd->char_slots ){
		chclif_moveCharSlotReply( fd, sd, from, 1 );
		return 1;
	}

	if( sd->found_char[to] > 0 ){
		// We want to move to a used position
		if( charserv_config.charmove_config.char_movetoused ){ // TODO: check if the target is in deletion process
			// Admin is friendly and uses triangle exchange
			if( SQL_ERROR == Sql_QueryStr(sql_handle, "START TRANSACTION")
				|| SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'",schema_config.char_db, to, sd->found_char[from] )
				|| SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", schema_config.char_db, from, sd->found_char[to] )
				|| SQL_ERROR == Sql_QueryStr(sql_handle, "COMMIT")
				){
				chclif_moveCharSlotReply( fd, sd, from, 1 );
				Sql_ShowDebug(sql_handle);
				Sql_QueryStr(sql_handle,"ROLLBACK");
				return 1;
			}
		}else{
			// Admin doesn't allow us to
			chclif_moveCharSlotReply( fd, sd, from, 1 );
			return 1;
		}
	}else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d'", schema_config.char_db, to, sd->found_char[from] ) ){
		Sql_ShowDebug(sql_handle);
		chclif_moveCharSlotReply( fd, sd, from, 1 );
		return 1;
	}

	if( (charserv_config.charmove_config.char_moves_unlimited)==0 ){
		sd->char_moves[from]--;
		Sql_Query(sql_handle, "UPDATE `%s` SET `moves`='%d' WHERE `char_id`='%d'", schema_config.char_db, sd->char_moves[from], sd->found_char[from] );
	}

	// We successfully moved the char - time to notify the client
	chclif_moveCharSlotReply( fd, sd, from, 0 );
	chclif_mmo_char_send(fd, sd);
	return 1;
}
Пример #27
0
/**
 * AH 0x2721
 * Retrieve account info from login-server, ask inter-server to tell player
 */
int chlogif_parse_AccInfoAck(int fd) {
	if (RFIFOREST(fd) < 19)
		return 0;
	else {
		int8 type = RFIFOB(fd, 18);
		if (type == 0 || RFIFOREST(fd) < 122+NAME_LENGTH) {
			mapif_accinfo_ack(false, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), 0, -1, 0, 0, NULL, NULL, NULL, NULL, NULL);
			RFIFOSKIP(fd,19);
			return 1;
		}
		type>>=1;
		mapif_accinfo_ack(true, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), type, RFIFOL(fd,19), RFIFOL(fd,23), RFIFOL(fd,27),
			RFIFOCP(fd,31), RFIFOCP(fd,71), RFIFOCP(fd,87), RFIFOCP(fd,111),
			RFIFOCP(fd,122));
		RFIFOSKIP(fd,122+NAME_LENGTH);
	}
	return 1;
}
Пример #28
0
/**
 * Map-serv requesting to send the list of sc_data the player has saved
 * @author [Skotlex]
 * @param fd: wich fd to parse from
 * @return : 0 not enough data received, 1 success
 */
int chmapif_parse_askscdata(int fd){
	if (RFIFOREST(fd) < 10)
		return 0;
	else {
#ifdef ENABLE_SC_SAVING
		int aid, cid;
		aid = RFIFOL(fd,2);
		cid = RFIFOL(fd,6);
		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",
			schema_config.scdata_db, aid, cid) )
		{
			Sql_ShowDebug(sql_handle);
			return 1;
		}
		if( Sql_NumRows(sql_handle) > 0 )
		{
			struct status_change_data scdata;
			int count;
			char* data;

			WFIFOHEAD(fd,14+50*sizeof(struct status_change_data));
			WFIFOW(fd,0) = 0x2b1d;
			WFIFOL(fd,4) = aid;
			WFIFOL(fd,8) = cid;
			for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count )
			{
				Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data);
				Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data);
				Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data);
				Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data);
				Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data);
				Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data);
				memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data));
			}
			if (count >= 50)
				ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid);
			if (count > 0)
			{
				WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data);
				WFIFOW(fd,12) = count;
				WFIFOSET(fd,WFIFOW(fd,2));
			}
		} else { // No Status Changes to load but still send a response
			WFIFOHEAD(fd,14);
			WFIFOW(fd,0) = 0x2b1d;
			WFIFOW(fd,2) = 14;
			WFIFOL(fd,4) = aid;
			WFIFOL(fd,8) = cid;
			WFIFOW(fd,12) = 0;
			WFIFOSET(fd,WFIFOW(fd,2));
		}
		Sql_FreeResult(sql_handle);
#endif
		RFIFOSKIP(fd, 10);
	}
	return 1;
}
Пример #29
0
int clif_parse_pre(int *fdPtr)
{
    const int fd = *fdPtr;

    int rest_len = (int)RFIFOREST(fd);
    if (rest_len < 2)
        return 0;

    struct map_session_data *sd = sockt->session[fd]->session_data;
    unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd);

    if (sd)
        parse_cmd_func = sd->parse_cmd_func;
    else
        parse_cmd_func = clif->parse_cmd;
    const unsigned int cmd = parse_cmd_func(fd, sd);

    char buf[100];
    sprintf(buf, "log/map_%d.log", fd);
    FILE *file = fopen(buf, "a");
    if (file == NULL)
    {
        ShowError("Cant open log file %s\n", buf);
        fclose(file);
        return 1;
    }

    const struct s_packet_db *packet = clif->packet(cmd);
    if (packet == NULL)
    {
        show_time(file);
        dump_client_map_error_packet(file, fd, cmd, rest_len);
        fclose(file);
        return 1;
    }

    int packet_len = packet->len;
    if (packet_len == -1)
    {
        if (rest_len < 4 || rest_len > 32768)
        {
            fclose(file);
            return 1;
        }
        packet_len = RFIFOW(fd, 2);
    }
    if (rest_len < packet_len)
    {
        fclose(file);
        return 1;
    }

    show_time(file);
    dump_client_map_packet(file, fd, cmd, rest_len, packet);
    fclose(file);
    return 0;
}
Пример #30
0
/**
 * Map-serv sent us his new users count, updating info
 * @param fd: wich fd to parse from
 * @param id: wich map_serv id
 * @return : 0 not enough data received, 1 success
 */
int chmapif_parse_getusercount(int fd, int id){
	if (RFIFOREST(fd) < 4)
		return 0;
	if (RFIFOW(fd,2) != map_server[id].users) {
		map_server[id].users = RFIFOW(fd,2);
		ShowInfo("User Count: %d (Server: %d)\n", map_server[id].users, id);
	}
	RFIFOSKIP(fd, 4);
	return 1;
}