r5185 - in trunk/data: . qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Wed Dec 10 04:19:15 EST 2008


Author: div0
Date: 2008-12-10 04:18:56 -0500 (Wed, 10 Dec 2008)
New Revision: 5185

Modified:
   trunk/data/defaultNexuiz.cfg
   trunk/data/qcsrc/server/extensions.qh
   trunk/data/qcsrc/server/ipban.qc
   trunk/data/qcsrc/server/ipban.qh
   trunk/data/qcsrc/server/miscfunctions.qc
Log:
added a simple way to sync ban lists online via a http server. CGI scripts for that not written yet.


Modified: trunk/data/defaultNexuiz.cfg
===================================================================
--- trunk/data/defaultNexuiz.cfg	2008-12-10 08:31:50 UTC (rev 5184)
+++ trunk/data/defaultNexuiz.cfg	2008-12-10 09:18:56 UTC (rev 5185)
@@ -1226,3 +1226,7 @@
 set g_touchexplode_force 150
 
 sbar_miniscoreboard_size 0 // this mode is broken in current csqc
+
+set g_ban_sync_uri "" // sync using this ban list provider (empty string to disable)
+set g_ban_sync_interval 5 // sync every 5 minutes
+set g_ban_sync_trusted_servers "" // request ban lists from these nexuiz servers (do not include your own server there, or unbanning may fail)

Modified: trunk/data/qcsrc/server/extensions.qh
===================================================================
--- trunk/data/qcsrc/server/extensions.qh	2008-12-10 08:31:50 UTC (rev 5184)
+++ trunk/data/qcsrc/server/extensions.qh	2008-12-10 09:18:56 UTC (rev 5185)
@@ -912,12 +912,15 @@
 //idea: div0
 //darkplaces implementation: div0
 //loads text from an URL into a string
+//returns 1 on success of initiation, 0 if there are too many concurrent
+//connections already or if the URL is invalid
 //the following callback will receive the data and MUST exist!
 //  void(float id, float status, string data) URI_Get_Callback;
 //status is either
 //  negative for an internal error,
 //  0 for success, or
 //  the HTTP response code on server error (e.g. 404)
+//if 1 is returned by uri_get, the callback will be called in the future
 float(string url, float id) uri_get = #513;
 
 //DP_SV_SPAWNFUNC_PREFIX

Modified: trunk/data/qcsrc/server/ipban.qc
===================================================================
--- trunk/data/qcsrc/server/ipban.qc	2008-12-10 08:31:50 UTC (rev 5184)
+++ trunk/data/qcsrc/server/ipban.qc	2008-12-10 09:18:56 UTC (rev 5185)
@@ -1,15 +1,152 @@
-float Ban_Insert(string ip, float bantime, string reason);
+float Ban_Insert(string ip, float bantime, string reason, float dosync);
 
 void OnlineBanList_SendBan(string ip, float bantime, string reason)
 {
-	// a stub
-	// fill in your ban list syncing here
+	string uri;
+
+	uri = cvar_string("g_ban_sync_uri");
+
+	if(uri == "")
+		return;
+
+	uri = strcat(uri, "?action=ban");
+	uri = strcat(uri, "&ip=", uri_escape(ip));
+	uri = strcat(uri, "&duration=", ftos(bantime));
+	uri = strcat(uri, "&why=", uri_escape(reason));
+
+	uri_get(uri, 0); // 0 = "discard" callback target
 }
 
+void OnlineBanList_SendUnban(string ip)
+{
+	string uri;
+
+	uri = cvar_string("g_ban_sync_uri");
+
+	if(uri == "")
+		return;
+
+	uri = strcat(uri, "?action=unban");
+	uri = strcat(uri, "&ip=", uri_escape(ip));
+
+	uri_get(uri, 0); // 0 = "discard" callback target
+}
+
+string OnlineBanList_Servers;
+float OnlineBanList_Timeout;
+
+void OnlineBanList_URI_Get_Callback(float status, string data)
+{
+	float n, i, j, l;
+	string ip;
+	float timeleft;
+	string reason;
+	string serverip;
+	float syncinterval;
+
+	if(time > OnlineBanList_Timeout)
+		return;
+	OnlineBanList_Timeout = 0;
+
+	syncinterval = cvar("g_ban_sync_interval");
+	if(syncinterval == 0)
+		return;
+	if(syncinterval > 0)
+		syncinterval *= 60;
+
+	if(status != 0)
+	{
+		print("Error receiving the online ban list.\nStatus is ", ftos(status), "\n");
+		return;
+	}
+
+	if(substring(data, 0, 1) == "<")
+	{
+		print("Error receiving the online ban list.\nReceived HTML instead of a ban list.\n");
+		return;
+	}
+
+	if(strstrofs(data, "\r", 0) != -1)
+	{
+		print("Error receiving the online ban list.\nReceived carriage returns.\n");
+		return;
+	}
+
+	n = tokenizebyseparator(data, "\n");
+	if(mod(n, 4) != 0)
+	{
+		print("Error receiving the online ban list.\nReceived invalid item count.\n");
+		return;
+	}
+
+	for(i = 0; i < n; i += 4)
+	{
+		ip = argv(i);
+		timeleft = stof(argv(i + 1));
+		reason = argv(i + 2);
+		serverip = argv(i + 3);
+
+		timeleft -= 15;
+		if(timeleft < 0)
+			continue;
+
+		l = strlen(ip);
+		for(j = 0; j < l; ++j)
+			if(strstrofs("0123456789.", substring(ip, j, 1), 0) == -1)
+			{
+				print("Invalid character ", substring(ip, j, 1), " in IP address ", ip, ". Skipping this ban.\n");
+				goto skip;
+			}
+
+		if(strstrofs(strcat(":", OnlineBanList_Servers, ":"), strcat(":", serverip, ":"), 0) != -1)
+		{
+			if(syncinterval > 0)
+				timeleft = min(syncinterval + 15, timeleft);
+				// 15 seconds for safety
+				// the ban will be prolonged on the next sync
+			Ban_Insert(ip, timeleft, strcat("ban synced from ", serverip), 0);
+			print("Ban list syncing: accepted ban of ", ip, " by ", serverip, ": ", reason, "\n");
+		}
+
+		continue;
+:skip
+	}
+}
+
 void OnlineBanList_Think()
 {
-	// a stub
-	// fill in your ban list syncing here
+	float argc;
+	string uri;
+	float i;
+	
+	uri = cvar_string("g_ban_sync_uri");
+
+	if(uri == "")
+		return;
+	if(cvar("g_ban_sync_interval") == 0) // < 0 is okay, it means "sync on level start only"
+		return;
+	argc = tokenize_sane(cvar_string("g_ban_sync_trusted_servers"));
+	if(argc == 0)
+		return;
+
+	if(OnlineBanList_Timeout == 0) // only if there is no ongoing request!
+	{
+		if(OnlineBanList_Servers)
+			strunzone(OnlineBanList_Servers);
+		OnlineBanList_Servers = argv(0);
+		for(i = 1; i < argc; ++i)
+			OnlineBanList_Servers = strcat(OnlineBanList_Servers, ":", argv(i));
+		OnlineBanList_Servers = strzone(OnlineBanList_Servers);
+		
+		uri = strcat(uri, "?action=list");
+		uri = strcat(uri, "&servers=", uri_escape(OnlineBanList_Servers));
+
+		OnlineBanList_Timeout = time + 10;
+		uri_get(uri, 1); // 1 = "banlist" callback target
+	}
+	
+	if(cvar("g_ban_sync_interval") > 0)
+		self.nextthink = time + max(60, cvar("g_ban_sync_interval") * 60);
 }
 
 #define BAN_MAX 64
@@ -55,7 +192,10 @@
 	if(ban_expire[i] == 0)
 		return FALSE;
 	if(ban_expire[i] > 0)
+	{
+		OnlineBanList_SendUnban(ban_ip[i]);
 		strunzone(ban_ip[i]);
+	}
 	ban_expire[i] = 0;
 	ban_ip[i] = "";
 	Ban_SaveBans();
@@ -115,15 +255,25 @@
 	return TRUE;
 }
 
-float Ban_IsClientBanned(entity client)
+float Ban_IsClientBanned(entity client, float idx)
 {
-	float i;
+	float i, b, e;
 	if(!ban_loaded)
 		Ban_LoadBans();
 	if(!Ban_GetClientIP(client))
 		return FALSE;
-	for(i = 0; i < ban_count; ++i)
+	if(idx < 0)
 	{
+		b = 0;
+		e = ban_count;
+	}
+	else
+	{
+		b = idx;
+		e = idx + 1;
+	}
+	for(i = b; i < e; ++i)
+	{
 		string s;
 		if(time > ban_expire[i])
 			continue;
@@ -138,7 +288,7 @@
 
 float Ban_MaybeEnforceBan(entity client)
 {
-	if(Ban_IsClientBanned(client))
+	if(Ban_IsClientBanned(client, -1))
 	{
 		string s;
 		s = strcat("^1NOTE:^7 banned client ", client.netaddress, " just tried to enter\n");
@@ -149,13 +299,15 @@
 	return FALSE;
 }
 
-float Ban_Insert(string ip, float bantime, string reason)
+float Ban_Insert(string ip, float bantime, string reason, float dosync)
 {
 	float i;
 	float j;
 	float bestscore;
+	entity e;
+	string s;
 
-	if(reason != "")
+	if(dosync)
 		OnlineBanList_SendBan(ip, bantime, reason);
 
 	// already banned?
@@ -164,7 +316,10 @@
 		{
 			// prolong the ban
 			if(time + bantime > ban_expire[i])
+			{
 				ban_expire[i] = time + bantime;
+				print(ip, "'s ban has been prolonged to ", ftos(bantime), " seconds from now\n");
+			}
 			// and abort
 			return FALSE;
 		}
@@ -199,6 +354,16 @@
 
 	Ban_SaveBans();
 
+	// Enforce our new ban
+	s = "";
+	FOR_EACH_REALCLIENT(e)
+		if(Ban_IsClientBanned(e, i))
+		{
+			s = strcat(s, "^1NOTE:^7 banned client ", e.netname, "^7 has to go\n");
+			dropclient(e);
+		}
+	bprint(s);
+
 	return TRUE;
 }
 
@@ -214,16 +379,16 @@
 	switch(masksize)
 	{
 		case 1:
-			Ban_Insert(ban_ip1, bantime, reason);
+			Ban_Insert(ban_ip1, bantime, reason, 1);
 			break;
 		case 2:
-			Ban_Insert(ban_ip2, bantime, reason);
+			Ban_Insert(ban_ip2, bantime, reason, 1);
 			break;
 		case 3:
-			Ban_Insert(ban_ip3, bantime, reason);
+			Ban_Insert(ban_ip3, bantime, reason, 1);
 			break;
 		default:
-			Ban_Insert(ban_ip4, bantime, reason);
+			Ban_Insert(ban_ip4, bantime, reason, 1);
 			break;
 	}
 	// and kick him
@@ -287,7 +452,7 @@
 				reason = substring(command, argv_start_index(3), strlen(command) - argv_start_index(3));
 			else
 				reason = "";
-			Ban_Insert(ip, bantime, reason);
+			Ban_Insert(ip, bantime, reason, 1);
 			return TRUE;
 		}
 	}

Modified: trunk/data/qcsrc/server/ipban.qh
===================================================================
--- trunk/data/qcsrc/server/ipban.qh	2008-12-10 08:31:50 UTC (rev 5184)
+++ trunk/data/qcsrc/server/ipban.qh	2008-12-10 09:18:56 UTC (rev 5185)
@@ -1,5 +1,6 @@
 void Ban_SaveBans();
 void Ban_LoadBans();
-float Ban_IsClientBanned(entity client);
 float Ban_MaybeEnforceBan(entity client);
 float GameCommand_Ban(string command);
+
+void OnlineBanList_URI_Get_Callback(float status, string data);

Modified: trunk/data/qcsrc/server/miscfunctions.qc
===================================================================
--- trunk/data/qcsrc/server/miscfunctions.qc	2008-12-10 08:31:50 UTC (rev 5184)
+++ trunk/data/qcsrc/server/miscfunctions.qc	2008-12-10 09:18:56 UTC (rev 5185)
@@ -1667,6 +1667,13 @@
 
 	switch(id)
 	{
+		case 0:
+			// 0 is the ID for discarding
+			break;
+		case 1:
+			// 1 is the ID for online ban list
+			OnlineBanList_URI_Get_Callback(status, data);
+			break;
 		default:
 			print("Received HTTP request data for an invalid id ", ftos(id), ".\n");
 			break;




More information about the nexuiz-commits mailing list