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

📄 connhelp.c

📁 Libnet is a cross-platform library aimed at game developers. It has an abstract high level API, whic
💻 C
📖 第 1 页 / 共 2 页
字号:
/*---------------------------------------------------------------- *   connhelp.c -- helper conn functions for drivers to use *---------------------------------------------------------------- *  libnet is (c) Copyright Chad Catlett and George Foot 1997-1998 * *  Please look in `docs' for details, documentation and *  distribution conditions. *//* These functions encapsulate the conn system on top of the channel * system.  Drivers can support the channels themselves, and set the * conn function entries in their struct to NULL.  Libnet will then * automatically redirect them to point at this driver, which chains * back to the real driver using the normal channel functions. */#include <stdlib.h>#include <string.h>#include <time.h>#include "platdefs.h"#include "libnet.h"#include "internal.h"#include "connhelp.h"#include "config.h"#include "timer.h"/*---------------------------------------- Settings for conn queues */struct conn_config {	/* Queue sizes -- these must be powers of two */	int outqueue_size, inqueue_size;	/* Time between resends of unacknowledged outgoing packets (ms) */	int resend_rate;};/* Defaults */static struct conn_config conn_config_default = { 16, 16, 500 };/* I'm feeling lazy, so I won't change these properly all through the code */#define CONN_CONFIG (conn->driver->conn_config?conn->driver->conn_config:&conn_config_default)#define MAX_OUTGOING_PACKETS   (CONN_CONFIG->outqueue_size)#define MAX_INCOMING_PACKETS   (CONN_CONFIG->inqueue_size)#define RESEND_RATE            (CONN_CONFIG->resend_rate)/*---------------------------------------- Data structures *//* The type used for index numbers.  This must be capable of storing 32-bit * unsigned integers. */typedef unsigned int index_t;/* Outgoing packet */struct out_packet_t {	index_t index;	int ack;	int last_send_time;	int size;	void *data;};/* Incoming packet */struct in_packet_t {	int size;	void *data;};/* Outgoing packet queue */struct out_t {	struct out_packet_t *packets;	index_t base_index;	index_t next_index;};/* Incoming packet queue */struct in_t {	struct in_packet_t *packets;	index_t base_index;};/* Connection list */struct conns_list {	struct conns_list *next;	NET_CHANNEL *chan;        /* channel we created for this client */	char *addr;               /* address of connecting client */	int client_conn_id;       /* client's quasi-unique ref for this conn */	struct conn_data_t *ref;  /* cross-reference to conn_data */	int last_access_time;     /* time when we were last used */};/* Internal data */struct conn_data_t {	NET_CHANNEL *chan;	char connect_string[12];	struct conns_list *conns;	struct out_t out;	struct in_t in;	struct conn_data_t *referer; /* pointer to listening conn refering to us */	int connect_timestamp;};/*---------------------------------------- Driver conn functions *//* create_queues: *  This sets up the packet queues for a conn. */static int create_queues (NET_CONN *conn){	struct conn_data_t *data = conn->data;	int i;		data->in.packets = malloc (MAX_INCOMING_PACKETS * sizeof *data->in.packets);	if (!data->in.packets) return 1;	for (i = 0; i < MAX_INCOMING_PACKETS; i++)		data->in.packets[i].data = NULL;	data->in.base_index = 1;	data->out.packets = malloc (MAX_OUTGOING_PACKETS * sizeof *data->out.packets);	if (!data->out.packets) {		free (data->in.packets);		return 1;	}	for (i = 0; i < MAX_OUTGOING_PACKETS; i++)		data->out.packets[i].data = NULL;	data->out.next_index = data->out.base_index = 1;		return 0;}static void destroy_queues (NET_CONN *conn){	struct conn_data_t *data = conn->data;	int i;	for (i = 0; i < MAX_INCOMING_PACKETS; i++)		if (data->in.packets[i].data)			free (data->in.packets[i].data);	for (i = 0; i < MAX_OUTGOING_PACKETS; i++)		if (data->out.packets[i].data)			free (data->out.packets[i].data);	free (data->in.packets);	free (data->out.packets);}/* init_conn: *  This just chains to the channel initialiser, basically. */static int init_conn (NET_CONN *conn, const char *addr){	struct conn_data_t *data;		conn->peer_addr[0] = '\0';		conn->data = data = malloc (sizeof *data);	if (!data) return 1;		if (create_queues (conn)) {		free (data);		return 2;	}		data->conns = NULL;	data->referer = NULL;		data->chan = net_openchannel (conn->type, addr);	if (!data->chan) {		destroy_queues (conn);		free (data);		return 3;	}	return 0; /* success */}static void destroy_conns_list (struct conns_list *conns){	struct conns_list *c;	while (conns) {		c = conns->next;		if (conns->ref)			conns->ref->referer = NULL;		free (conns->addr);		free (conns);		conns = c;	}}static int destroy_conn (NET_CONN *conn){	struct conn_data_t *data = conn->data;	if (data->referer)	{		/* remove us from refering list in listener connection */		struct conns_list *prev = NULL, *list = data->referer->conns;		while (list)		{			if (list->chan == data->chan)			{				struct conns_list *old = list;				if (prev)					prev->next = list->next;				else					data->referer->conns = list->next;				list = list->next;				free(old->addr);				free(old);			} else			{				prev = list;				list = list->next;			}		}	}	net_closechannel (data->chan);	destroy_queues (conn);	destroy_conns_list (data->conns);	free (data);	return 0;}/* listen: *  Here we need to set up the stub for the list of connectors.  We need *  this list because there's a (high) chance that we'll get multiple *  copies of the same connection request.  The list notes which *  addresses have requested connections, and which channel was created *  for each, so that we can return the same channel rather than opening *  another one. */static int listen (NET_CONN *conn){	struct conn_data_t *data = conn->data;		data->conns = malloc (sizeof *data->conns);	if (!data->conns) return 1;		data->conns->next = NULL;	data->conns->addr = NULL;	data->conns->chan = NULL;	data->conns->client_conn_id = -1;	data->conns->ref = NULL;		return 0;}/* get_channel: *  Scans the list of connections for one matching this connector, and  *  fills it in if found, returning positive.  Otherwise, adds a new entry *  to the list, fills it in, and returns negative.  On error, returns zero. */static int get_channel (struct conns_list *conns, const char *addr, int conn_id, int type, const char *bind, NET_CHANNEL **chan, struct conn_data_t *condat){#if 0	/* Before we do anything else, time out entries which have been here 	 * too long */	struct conns_list *ptr = conns;	while (ptr->next) {		if ((unsigned)(__libnet_timer_func() - ptr->last_access_time) > 10000) {			struct conns_list *ptr2 = ptr->next;			ptr->next = ptr2->next;			free (ptr2->addr);			free (ptr2);		}	}#endif	while (conns->next) {		conns = conns->next;		if ((conn_id == conns->client_conn_id) && !strcmp (addr, conns->addr)) {			*chan = conns->chan;			conns->last_access_time = __libnet_timer_func();			return 1;		}	}	conns->next = malloc (sizeof *conns->next);	if (conns->next) {		conns->next->next = NULL;		conns->next->addr = strdup (addr);		conns->next->client_conn_id = conn_id;		conns->next->ref = condat;		conns->next->last_access_time = __libnet_timer_func();		if (conns->next->addr) {			conns->next->chan = net_openchannel (type, bind);			if (conns->next->chan) {				*chan = conns->next->chan;				return -1;			}			free (conns->next->addr);		}		free (conns->next);		conns->next = NULL;	}	return 0;}/* poll_listen: *  Here we check for an incoming connection, and if there is one we *  fill in `newconn' with our data pointer for it and the addresses, *  and return nonzero.  Otherwise return 0. */static int poll_listen (NET_CONN *conn, NET_CONN *newconn){	struct conn_data_t *data;	char buffer[12], buffer2[8+NET_MAX_ADDRESS_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0 };	char addr[NET_MAX_ADDRESS_LENGTH];	int x;	int count = 32; /* maximum number of packets to process */	while (net_query (((struct conn_data_t *)conn->data)->chan) && count-- > 0) {		if ((net_receive (((struct conn_data_t *)conn->data)->chan, buffer, 12, addr) == 12) && !memcmp (buffer, "connect", 8)) {			newconn->data = data = malloc (sizeof *data);			if (!data) continue;			if (create_queues (newconn)) {				free (data);				continue;			}			data->conns = NULL;						x = get_channel (				((struct conn_data_t *)conn->data)->conns, addr,				(buffer[8] << 24) + (buffer[9] << 16) +				(buffer[10] << 8) + buffer[11],				conn->type, NULL, &data->chan, data			);						if (x) {				data->referer = conn->data;				/* tell new channel where to send in future */				net_assigntarget (data->chan, addr);				/* send reply now with address of new channel, through				 * listening conn so it can get through NATs */

⌨️ 快捷键说明

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