about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-07-25 07:24:57 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-07-25 07:24:57 +0000
commit1aecc644de9e2cb81e3f2fd6c8abc86f37debad7 (patch)
treea2a42c9e56b52cd0b9515f89dd6d862f14df24ff
parent52c987bfd7abcd8acecdc7da580b8e56be0bd625 (diff)
downloadzcatch-1aecc644de9e2cb81e3f2fd6c8abc86f37debad7.tar.gz
zcatch-1aecc644de9e2cb81e3f2fd6c8abc86f37debad7.zip
fixed errors in the network code
-rw-r--r--src/engine/client/client.cpp17
-rw-r--r--src/engine/network.cpp72
-rw-r--r--src/engine/server/server.cpp13
-rw-r--r--src/game/server/game_server.cpp8
4 files changed, 91 insertions, 19 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index 1d3b7d2b..dd7e895d 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -232,6 +232,7 @@ enum
 };
 
 static netaddr4 server_address;
+static const char *server_spam_address=0;
 
 static int state;
 static int get_state() { return state; }
@@ -319,6 +320,7 @@ void client::send_input()
 void client::disconnect()
 {
 	send_error("disconnected");
+	net.disconnect("disconnected");
 	set_state(STATE_OFFLINE);
 	map_unload();
 }
@@ -462,6 +464,9 @@ void client::run(const char *direct_connect_server)
 		// send input
 		if(get_state() == STATE_ONLINE)
 		{
+			if(server_spam_address)
+				disconnect();
+			
 			if(input_is_changed || time_get() > last_input+time_freq())
 			{
 				send_input();
@@ -470,6 +475,9 @@ void client::run(const char *direct_connect_server)
 			}
 		}
 		
+		if(get_state() == STATE_OFFLINE && server_spam_address)
+			client_connect(server_spam_address);
+		
 		// update input
 		inp_update();
 		
@@ -500,7 +508,7 @@ void client::run(const char *direct_connect_server)
 			break;
 
 		// be nice
-		//thread_sleep(1);
+		thread_sleep(1);
 		
 		if(reporttime < time_get())
 		{
@@ -844,6 +852,12 @@ int main(int argc, char **argv)
 			i++;
 			direct_connect_server = argv[i];
 		}
+		else if(argv[i][0] == '-' && argv[i][1] == 's' && argv[i][2] == 0 && argc - i > 1)
+		{
+			// -s SERVER:PORT
+			i++;
+			server_spam_address = argv[i];
+		}
 		else if(argv[i][0] == '-' && argv[i][1] == 'n' && argv[i][2] == 0 && argc - i > 1)
 		{
 			// -n NAME
@@ -855,6 +869,7 @@ int main(int argc, char **argv)
 			// -w
 			config.fullscreen = 0;
 		}
+		
 		else if(argv[i][0] == '-' && argv[i][1] == 'e' && argv[i][2] == 0)
 		{
 			editor = true;
diff --git a/src/engine/network.cpp b/src/engine/network.cpp
index c6b8207f..b8cf615d 100644
--- a/src/engine/network.cpp
+++ b/src/engine/network.cpp
@@ -15,7 +15,7 @@
 	header v2:
 		unsigned char flags;		1
 		unsigned char seq_ack[3];	4
-		unsigned char crc[2];		6
+		unsigned char token[2];		6
 */
 
 enum
@@ -40,6 +40,8 @@ enum
 	NETWORK_PACKETFLAG_CONNLESS=0x20,
 };
 
+static int current_token = 1;
+
 struct NETPACKETDATA
 {
 	unsigned char ID[2];
@@ -48,6 +50,7 @@ struct NETPACKETDATA
 	unsigned short seq;
 	unsigned short ack;
 	unsigned crc;
+	int token;
 	unsigned data_size;
 	int64 first_send_time;
 	unsigned char *data;
@@ -61,8 +64,8 @@ static void send_packet(NETSOCKET socket, NETADDR4 *addr, NETPACKETDATA *packet)
 	buffer[1] = ((packet->seq>>4)&0xf0) | ((packet->ack>>8)&0x0f);
 	buffer[2] = packet->seq;
 	buffer[3] = packet->ack;
-	buffer[4] = packet->crc>>8;
-	buffer[5] = packet->crc&0xff;
+	buffer[4] = packet->token>>8;
+	buffer[5] = packet->token&0xff;
 	mem_copy(buffer+NETWORK_HEADER_SIZE, packet->data, packet->data_size);
 	int send_size = NETWORK_HEADER_SIZE+packet->data_size;
 	//dbg_msg("network", "sending packet, size=%d (%d + %d)", send_size, NETWORK_HEADER_SIZE, packet->data_size);
@@ -75,6 +78,11 @@ struct NETCONNECTION
 	unsigned ack;
 	unsigned state;
 	
+	int token;
+	
+	int connected;
+	int disconnected;
+	
 	ring_buffer buffer;
 	
 	int64 last_recv_time;
@@ -88,7 +96,6 @@ struct NETCONNECTION
 
 struct NETSLOT
 {
-	int online;
 	NETCONNECTION conn;
 };
 
@@ -117,13 +124,20 @@ static void conn_reset(NETCONNECTION *conn)
 {
 	conn->seq = 0;
 	conn->ack = 0;
+	//dbg_msg("connection", "state = %d->%d", conn->state, NETWORK_CONNSTATE_OFFLINE);
+	
+	if(conn->state == NETWORK_CONNSTATE_ONLINE)
+		conn->disconnected++;
+		
 	conn->state = NETWORK_CONNSTATE_OFFLINE;
 	conn->error_string = 0;
 	conn->last_send_time = 0;
 	conn->last_recv_time = 0;
+	conn->token = -1;
 	conn->buffer.reset();
 }
 
+
 static const char *conn_error(NETCONNECTION *conn)
 {
 	return conn->error_string;
@@ -139,6 +153,8 @@ static void conn_init(NETCONNECTION *conn, NETSOCKET socket)
 	conn_reset(conn);
 	conn_reset_stats(conn);
 	conn->socket = socket;
+	conn->connected = 0;
+	conn->disconnected = 0;
 }
 
 static void conn_ack(NETCONNECTION *conn, int ack)
@@ -191,6 +207,7 @@ static void conn_send(NETCONNECTION *conn, int flags, int data_size, const void
 	p.seq = conn->seq;
 	p.ack = conn->ack;
 	p.crc = 0;
+	p.token = conn->token;
 	p.data_size = data_size;
 	p.data = (unsigned char *)data;
 	p.first_send_time = time_get();
@@ -216,30 +233,54 @@ static int conn_connect(NETCONNECTION *conn, NETADDR4 *addr)
 	// init connection
 	conn_reset(conn);
 	conn->peeraddr = *addr;
+	conn->token = current_token++;
+	//dbg_msg("connection", "state = %d->%d", conn->state, NETWORK_CONNSTATE_CONNECT);
 	conn->state = NETWORK_CONNSTATE_CONNECT;
 	conn_send(conn, NETWORK_PACKETFLAG_CONNECT, 0, 0);
 	return 0;
 }
 
+static void conn_disconnect(NETCONNECTION *conn)
+{
+	conn_send(conn, NETWORK_PACKETFLAG_CLOSE, 0, 0);
+	conn_reset(conn);
+}
+
 static int conn_feed(NETCONNECTION *conn, NETPACKETDATA *p, NETADDR4 *addr)
 {
 	conn->last_recv_time = time_get();
 	conn->stats.recv_packets++;
 	conn->stats.recv_bytes += p->data_size + NETWORK_HEADER_SIZE;
 	
+	if(p->flags&NETWORK_PACKETFLAG_CLOSE)
+	{
+		conn_reset(conn);
+		return 0;
+	}
+	
 	if(conn->state == NETWORK_CONNSTATE_OFFLINE)
 	{
 		if(p->flags == NETWORK_PACKETFLAG_CONNECT)
 		{
 			// send response and init connection
+			//dbg_msg("connection", "state = %d->%d", conn->state, NETWORK_CONNSTATE_ONLINE);
 			conn->state = NETWORK_CONNSTATE_ONLINE;
+			conn->connected++;
 			conn->peeraddr = *addr;
+			conn->token = p->token;
+			//dbg_msg("connection", "token set to %d", p->token);
 			conn_send(conn, NETWORK_PACKETFLAG_CONNECT|NETWORK_PACKETFLAG_ACCEPT, 0, 0);
 			dbg_msg("connection", "got connection, sending connect+accept");
 		}
 	}
 	else if(net_addr4_cmp(&conn->peeraddr, addr) == 0)
 	{
+		if(p->token != conn->token)
+		{
+			//dbg_msg("connection", "wrong token %d, %d", p->token, conn->token);
+			return 0;
+		}
+
 		if(conn->state == NETWORK_CONNSTATE_ONLINE)
 		{
 			// remove packages that are acked
@@ -276,7 +317,9 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETDATA *p, NETADDR4 *addr)
 			if(p->flags == (NETWORK_PACKETFLAG_CONNECT|NETWORK_PACKETFLAG_ACCEPT))
 			{
 				conn_send(conn, NETWORK_PACKETFLAG_ACCEPT, 0, 0);
+				//dbg_msg("connection", "state = %d->%d", conn->state, NETWORK_CONNSTATE_ONLINE);
 				conn->state = NETWORK_CONNSTATE_ONLINE;
+				conn->connected++;
 				dbg_msg("connection", "got connect+accept, sending accept. connection online");
 			}
 		}
@@ -292,6 +335,7 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETDATA *p, NETADDR4 *addr)
 		}*/
 		else
 		{
+			conn_reset(conn);
 			// strange packet, wrong state
 		}
 	}
@@ -315,6 +359,7 @@ static void conn_update(NETCONNECTION *conn)
 		conn->state != NETWORK_CONNSTATE_CONNECT &&
 		(time_get()-conn->last_recv_time) > time_freq()*3)
 	{
+		//dbg_msg("connection", "state = %d->%d", conn->state, NETWORK_CONNSTATE_ERROR);
 		conn->state = NETWORK_CONNSTATE_ERROR;
 		conn->error_string = "timeout";
 	}
@@ -322,6 +367,7 @@ static void conn_update(NETCONNECTION *conn)
 	// check for large buffer errors
 	if(conn->buffer.size() > 1024*64)
 	{
+		//dbg_msg("connection", "state = %d->%d", conn->state, NETWORK_CONNSTATE_ERROR);
 		conn->state = NETWORK_CONNSTATE_ERROR;
 		conn->error_string = "too weak connection (out of buffer)";
 	}
@@ -331,6 +377,7 @@ static void conn_update(NETCONNECTION *conn)
 		NETPACKETDATA *resend = (NETPACKETDATA *)conn->buffer.first()->data();
 		if(time_get()-resend->first_send_time > time_freq()*3)
 		{
+			//dbg_msg("connection", "state = %d->%d", conn->state, NETWORK_CONNSTATE_ERROR);
 			conn->state = NETWORK_CONNSTATE_ERROR;
 			conn->error_string = "too weak connection (not acked for 3 seconds)";
 		}
@@ -368,7 +415,8 @@ static int check_packet(unsigned char *buffer, int size, NETPACKETDATA *packet)
 	packet->flags = buffer[0];
 	packet->seq = ((buffer[1]&0xf0)<<4)|buffer[2];
 	packet->ack = ((buffer[1]&0x0f)<<8)|buffer[3];
-	packet->crc = (buffer[8]<<24)|(buffer[9]<<16)|(buffer[10]<<8)|buffer[11];
+	packet->crc = 0;
+	packet->token = (buffer[4]<<8)|buffer[5];
 	packet->data_size = size - NETWORK_HEADER_SIZE;
 	packet->data = buffer+NETWORK_HEADER_SIZE;
 	
@@ -407,9 +455,9 @@ int net_server_newclient(NETSERVER *s)
 {
 	for(int i = 0; i < NETWORK_MAX_CLIENTS; i++)
 	{
-		if(!s->slots[i].online && s->slots[i].conn.state == NETWORK_CONNSTATE_ONLINE)
+		if(s->slots[i].conn.connected)
 		{
-			s->slots[i].online = 1;
+			s->slots[i].conn.connected = 0;
 			return i;
 		}
 	}
@@ -421,9 +469,9 @@ int net_server_delclient(NETSERVER *s)
 {
 	for(int i = 0; i < NETWORK_MAX_CLIENTS; i++)
 	{
-		if(s->slots[i].online && s->slots[i].conn.state != NETWORK_CONNSTATE_ONLINE)
+		if(s->slots[i].conn.disconnected)
 		{
-			s->slots[i].online = 0;
+			s->slots[i].conn.disconnected = 0;
 			return i;
 		}
 	}
@@ -489,6 +537,7 @@ int net_server_recv(NETSERVER *s, NETPACKET *packet)
 							net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0)
 						{
 							found = 1; // silent ignore.. we got this client already
+							//dbg_msg("netserver", "ignored connect request %d", i);
 							break;
 						}
 					}
@@ -500,6 +549,7 @@ int net_server_recv(NETSERVER *s, NETPACKET *packet)
 						{
 							if(s->slots[i].conn.state == NETWORK_CONNSTATE_OFFLINE)
 							{
+								//dbg_msg("netserver", "connection started %d", i);
 								conn_feed(&s->slots[i].conn, &data, &addr);
 								found = 1;
 								break;
@@ -507,7 +557,7 @@ int net_server_recv(NETSERVER *s, NETPACKET *packet)
 						}
 					}
 					
-					if(!found)
+					if(found)
 					{
 						// TODO: send error
 					}
@@ -619,7 +669,7 @@ int net_client_disconnect(NETCLIENT *c, const char *reason)
 {
 	// TODO: do this more graceful
 	dbg_msg("net_client", "disconnected. reason=\"%s\"", reason);
-	conn_reset(&c->conn);
+	conn_disconnect(&c->conn);
 	return 0;
 }
 
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index 1af0da3b..d66fa2ee 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -410,9 +410,12 @@ public:
 			}
 			else if(msg == NETMSG_ENTERGAME)
 			{
-				dbg_msg("game", "player as entered the game. cid=%x", cid);
-				clients[cid].state = client::STATE_INGAME;
-				mods_client_enter(cid);
+				if(clients[cid].state != client::STATE_INGAME)
+				{
+					dbg_msg("game", "player as entered the game. cid=%x", cid);
+					clients[cid].state = client::STATE_INGAME;
+					mods_client_enter(cid);
+				}
 			}
 			else if(msg == NETMSG_INPUT)
 			{
@@ -532,8 +535,6 @@ public:
 			clients[cid].snapshots.purge_all();
 			
 			mods_client_drop(cid);
-			
-			dbg_msg("server", "del client %d", cid);
 		}
 		
 		// check for new clients
@@ -548,8 +549,6 @@ public:
 			clients[cid].clan[0] = 0;
 			clients[cid].snapshots.purge_all();
 			clients[cid].last_acked_snapshot = -1;
-			
-			dbg_msg("server", "new client %d", cid);
 		}
 	}
 };
diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp
index 9fb50d4b..31052aa5 100644
--- a/src/game/server/game_server.cpp
+++ b/src/game/server/game_server.cpp
@@ -242,6 +242,13 @@ int game_world::find_entities(vec2 pos, float radius, entity **ents, int max, co
 
 void game_world::insert_entity(entity *ent)
 {
+	entity *cur = first_entity;
+	while(cur)
+	{
+		dbg_assert(cur != ent, "err");
+		cur = cur->next_entity;
+	}
+	
 	// insert it
 	if(first_entity)
 		first_entity->prev_entity = ent;
@@ -1629,6 +1636,7 @@ void mods_client_enter(int client_id)
 
 void mods_client_drop(int client_id)
 {
+	dbg_msg("mods", "client drop %d", client_id);
 	players[client_id].client_id = -1;
 	world.remove_entity(&players[client_id]);
 }