⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connhelp.c

📁 Libnet is a cross-platform library aimed at game developers. It has an abstract high level API, whic
💻 C
📖 第 1 页 / 共 2 页
字号:
				net_assigntarget (((struct conn_data_t *)conn->data)->chan, addr);				strcpy (buffer2+8, net_getlocaladdress (data->chan));				net_send (((struct conn_data_t *)conn->data)->chan, buffer2, 8+NET_MAX_ADDRESS_LENGTH);			}						if (x >= 0) {				destroy_queues (newconn);				free (data);				continue;			}			strcpy (newconn->peer_addr, addr);			return 1;		}	}	return 0;}/* connect: *  Set the target address and send the first connection request.  This *  might not get through of course; later we can just repeat the send *  statement because the target address is already set.  No need to store *  it anywhere. */static int connect (NET_CONN *conn, const char *target){	int id;	static int next_id = 0;	struct conn_data_t *data = conn->data;	/* The id is a compound of the current time (with 1 second 	 * granularity), and an increasing counter.  The time is needed	 * because the counter resets when you restart the program, and 	 * the counter is needed because of the granularity of the time. */	/* Strictly, this line needs a mutex, but there's nowhere around 	 * here we can call `MUTEX_CREATE'. */	id = (next_id++ << 16) + (time(NULL) & 0xffff);	strcpy (data->connect_string, "connect");	data->connect_string[8] = (id >> 24) & 0xff;	data->connect_string[9] = (id >> 16) & 0xff;	data->connect_string[10] = (id >> 8) & 0xff;	data->connect_string[11] = id & 0xff;		if (net_assigntarget (data->chan, target)) return 1;	if (net_send (data->chan, data->connect_string, 12)) return 2;	data->connect_timestamp = __libnet_timer_func();	return 0;}/* poll_connect: *  This function does two things.  Firstly it checks for a response from  *  the server.  If there's no response, it then resends the connection  *  request. * *  The possible problem here is that the server's response might just be *  delayed.  The best way I can see around this problem is for the server *  to keep an eye on the return addresses of the connection attempts, and *  not open a fresh channel each time a duplicate of an old packet arrives. *  This actually kills two birds with one stone, since if either the  *  client's request packet or the server's response packet are dropped, the *  client will eventually resend, causing the server to send an identical  *  response. * *  Later note:  In fact we needed to introduce an almost-unique identifier *  to pass as well, since the channel's address may be reused later on. */static int poll_connect (NET_CONN *conn){	struct conn_data_t *data = conn->data;	char buffer[8+NET_MAX_ADDRESS_LENGTH];	char addr[NET_MAX_ADDRESS_LENGTH];		if ((net_receive (data->chan, buffer, 8+NET_MAX_ADDRESS_LENGTH, addr) == 8+NET_MAX_ADDRESS_LENGTH) && (!memcmp (buffer, "\0\0\0\0\0\0\0", 8))) {		net_fixupaddress_channel(data->chan, &buffer[8], addr);		net_assigntarget (data->chan, addr);		strcpy (conn->peer_addr, addr);		return 1;	}	/* No response */	{		unsigned long clock_value = __libnet_timer_func();		if ((unsigned)(clock_value - data->connect_timestamp) > RESEND_RATE) {			net_send (data->chan, data->connect_string, 8);			data->connect_timestamp = clock_value;		}	}	return 0;}/* poll: *  This function handles all the true I/O for the RDMs. */static void poll (NET_CONN *conn){	struct conn_data_t *data = conn->data;		/* First check whether anything in the outgoing queue needs sending */	{		struct out_packet_t *outp;		int clock_value = __libnet_timer_func(), i;		for (i = 0; i < MAX_OUTGOING_PACKETS; i++) {			outp = data->out.packets + i;			if ((outp->data) && (!outp->ack) && ((unsigned)(clock_value - outp->last_send_time) > RESEND_RATE)) {				net_send (data->chan, outp->data, outp->size + 4);				outp->last_send_time = clock_value;			}		}	}		/* Then receive any incoming data */	{		int count = 10;  /* max num of packets [we're not meant to block] */		unsigned char receive_buffer[16384];				while (count--) {			int x;			unsigned id;			x = net_receive (data->chan, receive_buffer, sizeof receive_buffer, 0);			if ((x == 0) || (x == -1)) break; /* quit if no more data or error */			if (x < 4) continue;    /* badly formed packet -- no ID */			id = 0;			id = (id << 8) + receive_buffer[3];			id = (id << 8) + receive_buffer[2];			id = (id << 8) + receive_buffer[1];			id = (id << 8) + receive_buffer[0];			if (id == 0) {    /* it's an acknowledgement */				if (x != 8) continue;   /* badly formed */				id = (id << 8) + receive_buffer[7];				id = (id << 8) + receive_buffer[6];				id = (id << 8) + receive_buffer[5];				id = (id << 8) + receive_buffer[4];				if (id >= data->out.base_index)					data->out.packets[id % MAX_OUTGOING_PACKETS].ack = 1;				if (id == data->out.base_index) {					int i, j = id % MAX_OUTGOING_PACKETS;					for (i = 0; i < MAX_OUTGOING_PACKETS; i++) {						if (!data->out.packets[j].ack || !data->out.packets[j].data) break;						data->out.base_index++;						free (data->out.packets[j].data);						data->out.packets[j].data = NULL;						j = (j + 1) % MAX_OUTGOING_PACKETS;					}				}				continue;			}						if (x == 4) continue;          /* zero length */						if (id >= data->in.base_index + MAX_INCOMING_PACKETS)				continue;			if (id >= data->in.base_index) {				struct in_packet_t *ptr = data->in.packets + id % MAX_INCOMING_PACKETS;				if (!ptr->data) {   /* haven't got this one yet */					ptr->data = malloc (x - 4);					if (!ptr->data) continue;					memcpy (ptr->data, receive_buffer + 4, x - 4);					ptr->size = x - 4;				}			}			/* Acknowledge */			{				char buf[8] = { 0 };				memcpy (buf + 4, receive_buffer, 4);				net_send (data->chan, buf, 8);			}		}	}}/* send_rdm: *  Sends an RDM down a conn.  Returns 0 on success, anything else on *  failure.  Could fail if the queue is full. */static int send_rdm (NET_CONN *conn, const void *buf, int size){	struct conn_data_t *data = conn->data;	struct out_packet_t *outp;	if ((size <= 0) || (data->out.next_index >= data->out.base_index + MAX_OUTGOING_PACKETS - 1)) {		poll(conn); /* poll so that eventually the send queue will decrease */		return -1;	}		outp = data->out.packets + (data->out.next_index % MAX_OUTGOING_PACKETS);	outp->data = malloc (size + 4);	if (!outp->data) return -1;	outp->index = data->out.next_index++;	outp->ack = 0;	outp->last_send_time = 0;	outp->size = size;		((char *)outp->data)[0] =  outp->index        & 0xff;	((char *)outp->data)[1] = (outp->index >> 8)  & 0xff;	((char *)outp->data)[2] = (outp->index >> 16) & 0xff;	((char *)outp->data)[3] = (outp->index >> 24) & 0xff;	memcpy (((char *)outp->data) + 4, buf, size);		poll (conn); /* dispatch the packet immediately */	return 0;}/* recv_rdm: *  Tries to receive one RDM from the conn.  Return the number of bytes *  received, or negative on error.  -1 = buffer too small. */static int recv_rdm (NET_CONN *conn, void *buf, int max){	struct conn_data_t *data = conn->data;	struct in_packet_t *packet;	poll (conn);	packet = data->in.packets + (data->in.base_index % MAX_INCOMING_PACKETS);	if (!packet->data) return 0;	if (packet->size > max) {		memcpy (buf, packet->data, max);		return -1;	}	memcpy (buf, packet->data, packet->size);	free (packet->data);	packet->data = NULL;	data->in.base_index++;	return packet->size;}/* ignore_rdm: *  Causes the next incoming packet (if any) to be dropped.  For use *  when, for whatever reason, a huge packet drifts into the queue *  and you aren't expecting to have to deal with it.  Returns 1 if *  a packet was ignored, zero otherwise. */static int ignore_rdm (NET_CONN *conn){        struct conn_data_t *data = conn->data;        struct in_packet_t *packet;        poll (conn);        packet = data->in.packets + (data->in.base_index % MAX_INCOMING_PACKETS);        if (!packet->data) return 0;	free (packet->data);        packet->data = NULL;        data->in.base_index++;        return 1;}/* query_rdm: *  Tests for incoming data on the conn.  Returns the amount of data in the *  first queued packet, or zero if none are queued. */static int query_rdm (NET_CONN *conn){	struct conn_data_t *data = conn->data;	poll (conn);	if (data->in.packets[data->in.base_index % MAX_INCOMING_PACKETS].data)		return data->in.packets[data->in.base_index % MAX_INCOMING_PACKETS].size;	else		return 0;}/* conn_stats: *  Fills in the number of packets in the in and/or out queues.  Pass *  NULL if you don't care about one of them. */static int conn_stats (NET_CONN *conn, int *in_q, int *out_q){	struct conn_data_t *data = conn->data;	poll (conn);		if (in_q) {		int i;		*in_q = 0;		for (i = 0; i < MAX_INCOMING_PACKETS; i++)			if (data->in.packets[i].data) (*in_q)++;	}	if (out_q) *out_q = data->out.next_index - data->out.base_index;	return 0;}/* load_conn_config: *  Loads conn config information from the given section. */static void load_conn_config (NET_DRIVER *drv, FILE *fp, const char *section){	char *option, *value;		if (!drv->conn_config) {		drv->conn_config = malloc (sizeof *drv->conn_config);		if (!drv->conn_config) return;		memcpy (drv->conn_config, &conn_config_default, sizeof conn_config_default);	}	if (__libnet_internal__seek_section (fp, section)) return;		while (__libnet_internal__get_setting (fp, &option, &value) == 0) {		if (!strcmp (option, "conn_outqueue_size")) {			unsigned int x = atoi (value), y = 1;			while (y && (y < x)) y <<= 1;			if (!y) y = conn_config_default.outqueue_size;			drv->conn_config->outqueue_size = y;		} else if (!strcmp (option, "conn_inqueue_size")) {			unsigned int x = atoi (value), y = 1;			while (y && (y < x)) y <<= 1;			if (!y) y = conn_config_default.inqueue_size;			drv->conn_config->inqueue_size = y;		} else if (!strcmp (option, "conn_resend_rate")) {			unsigned int x = atoi (value);			if (!x) x = conn_config_default.resend_rate;			drv->conn_config->resend_rate = x;		}	}}NET_DRIVER __libnet_internal__wrapper_driver = {	"Wrapper driver",	NULL,                    /* desc */	NET_CLASS_NONE,		NULL, NULL, NULL,        /* detect, init, exit */		NULL, NULL,              /* prepareaddress, poll_prepareaddress */		NULL, NULL,              /* init_channel, destroy_channel */	NULL, NULL, NULL, NULL,  /* update_target, send, recv, query */		init_conn, destroy_conn,	listen, poll_listen, connect, poll_connect,		send_rdm,	recv_rdm,	query_rdm,	ignore_rdm,	conn_stats,	NULL,                    /* load_config */	load_conn_config,	NULL};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -