فهرست منبع

Introducing rAthena's anonymous data collector. This aims at improving rAthena's overall features by letting we know which options are most and least used.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16785 54d463be-8e91-2dee-dedb-b68131a5f0ec
shennetsind 12 سال پیش
والد
کامیت
56256a4532
8فایلهای تغییر یافته به همراه214 افزوده شده و 28 حذف شده
  1. 30 1
      src/char/char.c
  2. 1 0
      src/char/inter.c
  3. 5 4
      src/common/socket.c
  4. 1 1
      src/common/socket.h
  5. 18 18
      src/config/core.h
  6. 142 0
      src/map/battle.c
  7. 15 1
      src/map/chrif.c
  8. 2 3
      src/map/chrif.h

+ 30 - 1
src/char/char.c

@@ -3285,6 +3285,35 @@ int parse_frommap(int fd)
 			RFIFOSKIP(fd,6);
 		break;
 
+		case 0x3008:
+			if( RFIFOREST(fd) < RFIFOW(fd,4) )
+				return 0;/* packet wasn't fully received yet (still fragmented) */
+			else {
+				int sfd;/* stat server fd */
+				RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */
+			
+				if( (sfd = make_connection(host2ip("stats.rathena.org"),(uint16)25421,true) ) == -1 ) {
+					RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */
+					break;/* connection not possible, we drop the report */
+				}
+			
+				session[sfd]->flag.server = 1;/* to ensure we won't drop our own packet */
+			
+				WFIFOHEAD(sfd, RFIFOW(fd,2) );
+				
+				memcpy((char*)WFIFOP(sfd,0), (char*)RFIFOP(fd, 0), RFIFOW(fd,2));
+				
+				WFIFOSET(sfd, RFIFOW(fd,2) );
+				
+				flush_fifo(sfd);
+				
+				do_close(sfd);
+				
+				RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */
+		}
+		break;
+
+				
 		default:
 		{
 			// inter server - packet
@@ -4244,7 +4273,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data
 		return 0;
 
 	ShowInfo("Attempt to connect to login-server...\n");
-	login_fd = make_connection(login_ip, login_port);
+	login_fd = make_connection(login_ip, login_port, false);
 	if (login_fd == -1)
 	{	//Try again later. [Skotlex]
 		login_fd = 0;

+ 1 - 0
src/char/inter.c

@@ -1220,6 +1220,7 @@ int inter_parse_frommap(int fd)
 	case 0x3005: mapif_parse_RegistryRequest(fd); break;
 	case 0x3006: mapif_parse_NameChangeRequest(fd); break;
 	case 0x3007: mapif_parse_accinfo(fd); break;
+	/* 0x3008 is used by the report stuff */
 	default:
 		if(  inter_party_parse_frommap(fd)
 		  || inter_guild_parse_frommap(fd)

+ 5 - 4
src/common/socket.c

@@ -502,8 +502,7 @@ int make_listen_bind(uint32 ip, uint16 port)
 	return fd;
 }
 
-int make_connection(uint32 ip, uint16 port)
-{
+int make_connection(uint32 ip, uint16 port, bool silent) {
 	struct sockaddr_in remote_address;
 	int fd;
 	int result;
@@ -533,11 +532,13 @@ int make_connection(uint32 ip, uint16 port)
 	remote_address.sin_addr.s_addr = htonl(ip);
 	remote_address.sin_port        = htons(port);
 
-	ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
+	if( !silent )
+		ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
 
 	result = sConnect(fd, (struct sockaddr *)(&remote_address), sizeof(struct sockaddr_in));
 	if( result == SOCKET_ERROR ) {
-		ShowError("make_connection: connect failed (socket #%d, %s)!\n", fd, error_msg());
+		if( !silent )
+			ShowError("make_connection: connect failed (socket #%d, %s)!\n", fd, error_msg());
 		do_close(fd);
 		return -1;
 	}

+ 1 - 1
src/common/socket.h

@@ -112,7 +112,7 @@ extern bool session_isActive(int fd);
 // Function prototype declaration
 
 int make_listen_bind(uint32 ip, uint16 port);
-int make_connection(uint32 ip, uint16 port);
+int make_connection(uint32 ip, uint16 port, bool silent);
 int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size);
 int realloc_writefifo(int fd, size_t addition);
 int WFIFOSET(int fd, size_t len);

+ 18 - 18
src/config/core.h

@@ -8,20 +8,16 @@
  * For detailed guidance on these check http://rathena.org/wiki/SRC/config/
  **/
 
-/**
- * Max number of items on @autolootid list
- **/
+/// Max number of items on @autolootid list
 #define AUTOLOOTITEM_SIZE 10
 
-/**
- * The maximum number of atcommand suggestions
- **/
+/// The maximum number of atcommand suggestions
 #define MAX_SUGGESTIONS 10
 
-//Comment to disable the official walk path
-// -- The official walkpath disables users from taking non-clear walk paths,
-// -- e.g. if they want to get around an obstacle they have to walk around it,
-// -- while with OFFICIAL_WALKPATH disabled if they click to walk around a obstacle the server will do it automatically
+/// Comment to disable the official walk path
+/// The official walkpath disables users from taking non-clear walk paths,
+/// e.g. if they want to get around an obstacle they have to walk around it,
+/// while with OFFICIAL_WALKPATH disabled if they click to walk around a obstacle the server will do it automatically
 #define OFFICIAL_WALKPATH
 
 /// leave this line uncommented to enable callfunc checks when processing scripts.
@@ -31,21 +27,25 @@
 /// your map-server using more resources while this is active, comment the line
 #define SCRIPT_CALLFUNC_CHECK
 
+/// Uncomment to disable rAthena's anonymous stat report
+/// We kindly ask you to consider keeping it enabled, it helps us improve rAthena.
+//#define STATS_OPT_OUT
+
 /// uncomment to enable query_sql script command and mysql logs to function on it's own thread
 /// be aware this feature is under tests and you should use at your own risk, we however
 /// welcome any feedback you may have regarding this feature, please send us all bug reports.
 //#define BETA_THREAD_TEST
 
-//Uncomment to enable the Cell Stack Limit mod.
-//It's only config is the battle_config cell_stack_limit.
-//Only chars affected are those defined in BL_CHAR (mobs and players currently)
+/// Uncomment to enable the Cell Stack Limit mod.
+/// It's only config is the battle_config cell_stack_limit.
+/// Only chars affected are those defined in BL_CHAR (mobs and players currently)
 //#define CELL_NOSTACK
 
-//Uncomment to enable circular area checks.
-//By default, all range checks in Aegis are of Square shapes, so a weapon range
-//  of 10 allows you to attack from anywhere within a 21x21 area.
-//Enabling this changes such checks to circular checks, which is more realistic,
-//  but is not the official behaviour.
+/// Uncomment to enable circular area checks.
+/// By default, all range checks in Aegis are of Square shapes, so a weapon range
+/// - of 10 allows you to attack from anywhere within a 21x21 area.
+/// Enabling this changes such checks to circular checks, which is more realistic,
+/// - but is not the official behaviour.
 //#define CIRCULAR_AREA
 
 /**

+ 142 - 0
src/map/battle.c

@@ -8,6 +8,7 @@
 #include "../common/showmsg.h"
 #include "../common/ers.h"
 #include "../common/random.h"
+#include "../common/socket.h"
 #include "../common/strlib.h"
 #include "../common/utils.h"
 
@@ -27,6 +28,7 @@
 #include "party.h"
 #include "battle.h"
 #include "battleground.h"
+#include "chrif.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -5717,7 +5719,141 @@ static const struct _battle_data {
 	{ "homunculus_max_level",               &battle_config.hom_max_level,                   99,     0,      MAX_LEVEL,      },
 	{ "homunculus_S_max_level",             &battle_config.hom_S_max_level,                 150,    0,      MAX_LEVEL,      },
 };
+#ifndef STATS_OPT_OUT
+/**
+ * rAthena anonymous statistic usage report -- packet is built here, and sent to char server to report.
+ **/
+void rAthena_report(char* date, char *time_c) {
+	int i, rev = 0, bd_size = ARRAYLENGTH(battle_data);
+	unsigned int config = 0;
+	const char* rev_str;
+	char timestring[25];
+	time_t curtime;
+	char* buf;
+
+	enum config_table {
+		C_CIRCULAR_AREA         = 0x0001,
+		C_CELLNOSTACK           = 0x0002,
+		C_BETA_THREAD_TEST      = 0x0004,
+		C_SCRIPT_CALLFUNC_CHECK = 0x0008,
+		C_OFFICIAL_WALKPATH     = 0x0010,
+		C_RENEWAL               = 0x0020,
+		C_RENEWAL_CAST          = 0x0040,
+		C_RENEWAL_DROP          = 0x0080,
+		C_RENEWAL_EXP           = 0x0100,
+		C_RENEWAL_LVDMG         = 0x0200,
+		C_RENEWAL_EDP           = 0x0400,
+		C_RENEWAL_ASPD          = 0x0800,
+		C_SECURE_NPCTIMEOUT     = 0x1000,
+		C_SQL_DBS               = 0x2000,
+		C_SQL_LOGS              = 0x4000,
+	};
+		
+	if( (rev_str = get_svn_revision()) != 0 )
+		rev = atoi(rev_str);
+	
+	/* we get the current time */
+	time(&curtime);
+	strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", localtime(&curtime));
+	
+	
+#ifdef CIRCULAR_AREA
+	config |= C_CIRCULAR_AREA;
+#endif
+	
+#ifdef CELL_NOSTACK
+	config |= C_CELLNOSTACK;
+#endif
+	
+#ifdef BETA_THREAD_TEST
+	config |= C_BETA_THREAD_TEST;
+#endif
+
+#ifdef SCRIPT_CALLFUNC_CHECK
+	config |= C_SCRIPT_CALLFUNC_CHECK;
+#endif
+
+#ifdef OFFICIAL_WALKPATH
+	config |= C_OFFICIAL_WALKPATH;
+#endif
+
+#ifdef RENEWAL
+	config |= C_RENEWAL;
+#endif
+	
+#ifdef RENEWAL_CAST
+	config |= C_RENEWAL_CAST;
+#endif
+
+#ifdef RENEWAL_DROP
+	config |= C_RENEWAL_DROP;
+#endif
+
+#ifdef RENEWAL_EXP
+	config |= C_RENEWAL_EXP;
+#endif
+	
+#ifdef RENEWAL_LVDMG
+	config |= C_RENEWAL_LVDMG;
+#endif
 
+#ifdef RENEWAL_EDP
+	config |= C_RENEWAL_EDP;
+#endif
+	
+#ifdef RENEWAL_ASPD
+	config |= C_RENEWAL_ASPD;
+#endif
+	
+/* not a ifdef because SECURE_NPCTIMEOUT is always defined, but either as 0 or higher */
+#if SECURE_NPCTIMEOUT
+	config |= C_SECURE_NPCTIMEOUT;
+#endif
+	/* non-define part */
+	if( db_use_sqldbs )
+		config |= C_SQL_DBS;
+	
+	if( log_config.sql_logs )
+		config |= C_SQL_LOGS;
+	
+#define BFLAG_LENGTH 35
+	
+	CREATE(buf, char, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 );
+	
+	/* build packet */
+
+	WBUFW(buf,0) = 0x3000;
+	WBUFW(buf,2) = 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) );
+	WBUFW(buf,4) = 0x9c;
+
+	safestrncpy((char*)WBUFP(buf,6), date, 12);
+	safestrncpy((char*)WBUFP(buf,6 + 12), time_c, 9);
+	safestrncpy((char*)WBUFP(buf,6 + 12 + 9), timestring, 24);
+	
+	WBUFL(buf,6 + 12 + 9 + 24)         = rev;	
+	WBUFL(buf,6 + 12 + 9 + 24 + 4)     = map_getusers();
+	
+	WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4) = config;
+	WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4 + 4) = bd_size;
+	
+	for( i = 0; i < bd_size; i++ ) {
+		safestrncpy((char*)WBUFP(buf,6 + 12 + 9+ 24  + 4 + 4 + 4 + 4 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, 35);
+		WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 )  )  ) = *battle_data[i].val;
+	}	
+		
+	chrif_send_report(buf,  6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) );
+	
+	aFree(buf);
+	
+#undef BFLAG_LENGTH
+}
+static int rAthena_report_timer(int tid, unsigned int tick, int id, intptr_t data) {
+	if( chrif_isconnected() ) {/* char server relays it, so it must be online. */
+		rAthena_report(__DATE__,__TIME__);
+	}
+	return 0;
+}
+#endif
 
 int battle_set_value(const char* w1, const char* w2)
 {
@@ -5841,6 +5977,12 @@ void do_init_battle(void)
 {
 	delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR);
 	add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub");
+	
+#ifndef STATS_OPT_OUT
+	add_timer_func_list(rAthena_report_timer, "rAthena_report_timer");
+	add_timer_interval(gettick()+30000, rAthena_report_timer, 0, 0, 60000 * 30);
+#endif
+
 }
 
 void do_final_battle(void)

+ 15 - 1
src/map/chrif.c

@@ -1523,7 +1523,7 @@ static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_
 		}
 
 		chrif_state = 0;
-		char_fd = make_connection(char_ip, char_port);
+		char_fd = make_connection(char_ip, char_port,false);
 		if (char_fd == -1)
 		{	//Attempt to connect later. [Skotlex]
 			return 0;
@@ -1562,6 +1562,20 @@ int chrif_removefriend(int char_id, int friend_id) {
 	return 0;
 }
 
+void chrif_send_report(char* buf, int len) {
+#ifndef STATS_OPT_OUT
+	WFIFOHEAD(char_fd,len + 2);
+	
+	WFIFOW(char_fd,0) = 0x3008;
+	
+	memcpy(WFIFOP(char_fd,2), buf, len);
+	
+	WFIFOSET(char_fd,len + 2);
+	
+	flush_fifo(char_fd); /* ensure it's sent now. */
+#endif
+}
+
 /**
  * @see DBApply
  */

+ 2 - 3
src/map/chrif.h

@@ -57,10 +57,9 @@ int chrif_char_online(struct map_session_data *sd);
 int chrif_changesex(struct map_session_data *sd);
 int chrif_chardisconnect(struct map_session_data *sd);
 int chrif_divorce(int partner_id1, int partner_id2);
-/**
- * rAthena
- **/
+
 int chrif_removefriend(int char_id, int friend_id);
+void chrif_send_report(char* buf, int len);
 
 int do_final_chrif(void);
 int do_init_chrif(void);