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

📄 proxy.c

📁 BlueZ源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		*ctrl |= PARODD;	} else if (strcasecmp("mark", str) == 0)		*ctrl |= PARENB;	else if ((strcasecmp("none", str) == 0) ||			(strcasecmp("space", str) == 0))		*ctrl &= ~PARENB;	else		return -1;	return 0;}static int set_databits(uint8_t databits, tcflag_t *ctrl){	if (databits < 5 || databits > 8)		return -EINVAL;	*ctrl &= ~CSIZE;	switch (databits) {	case 5:		*ctrl |= CS5;		break;	case 6:		*ctrl |= CS6;		break;	case 7:		*ctrl |= CS7;		break;	case 8:		*ctrl |= CS8;		break;	}	return 0;}static int set_stopbits(uint8_t stopbits, tcflag_t *ctrl){	/* 1.5 will not be allowed */	switch (stopbits) {	case 1:		*ctrl &= ~CSTOPB;		return 0;	case 2:		*ctrl |= CSTOPB;		return 0;	}	return -EINVAL;}static DBusMessage *proxy_set_serial_params(DBusConnection *conn,						DBusMessage *msg, void *data){	struct serial_proxy *prx = data;	struct serial_adapter *adapter = prx->adapter;	const char *ratestr, *paritystr;	uint8_t databits, stopbits;	tcflag_t ctrl;		/* Control mode flags */	speed_t speed = B0;	/* In/Out speed */	/* Don't allow change TTY settings if it is open */	if (prx->local_watch)		return failed(msg, "Not allowed");	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &ratestr,				DBUS_TYPE_BYTE, &databits,				DBUS_TYPE_BYTE, &stopbits,				DBUS_TYPE_STRING, &paritystr,				DBUS_TYPE_INVALID))		return NULL;	if (str2speed(ratestr, &speed)  == B0)		return invalid_arguments(msg, "Invalid baud rate");	ctrl = prx->proxy_ti.c_cflag;	if (set_databits(databits, &ctrl) < 0)		return invalid_arguments(msg, "Invalid data bits");	if (set_stopbits(stopbits, &ctrl) < 0)		return invalid_arguments(msg, "Invalid stop bits");	if (set_parity(paritystr, &ctrl) < 0)		return invalid_arguments(msg, "Invalid parity");	prx->proxy_ti.c_cflag = ctrl;	prx->proxy_ti.c_cflag |= (CLOCAL | CREAD);	cfsetispeed(&prx->proxy_ti, speed);	cfsetospeed(&prx->proxy_ti, speed);	proxy_store(&adapter->src, prx->uuid128, prx->address, NULL,				prx->channel, 0, &prx->proxy_ti);	return dbus_message_new_method_return(msg);}static GDBusMethodTable proxy_methods[] = {	{ "Enable",			"",	"",	proxy_enable },	{ "Disable",			"",	"",	proxy_disable },	{ "GetInfo",			"",	"a{sv}",proxy_get_info },	{ "SetSerialParameters",	"syys",	"",	proxy_set_serial_params },	{ },};static void proxy_path_unregister(gpointer data){	struct serial_proxy *prx = data;	int sk;	info("Unregistered proxy: %s", prx->address);	if (prx->type != TTY_PROXY)		goto done;	/* Restore the initial TTY configuration */	sk =  open(prx->address, O_RDWR | O_NOCTTY);	if (sk) {		tcsetattr(sk, TCSAFLUSH, &prx->sys_ti);		close(sk);	}done:	proxy_free(prx);}static int register_proxy_object(struct serial_proxy *prx, char *outpath, size_t size){	struct serial_adapter *adapter = prx->adapter;	char path[MAX_PATH_LENGTH + 1];	snprintf(path, MAX_PATH_LENGTH, "%s/proxy%d",			adapter->path, sk_counter++);	if (!g_dbus_register_interface(adapter->conn, path,					SERIAL_PROXY_INTERFACE,					proxy_methods, NULL, NULL,					prx, proxy_path_unregister)) {		error("D-Bus failed to register %s path", path);		return -1;	}	prx->path = g_strdup(path);	adapter->proxies = g_slist_append(adapter->proxies, prx);	if (outpath)		strncpy(outpath, path, size);	info("Registered proxy: %s", path);	return 0;}static int proxy_tty_register(struct serial_adapter *adapter,				const char *uuid128, const char *address,				struct termios *ti, char *outpath, size_t size,				gboolean save){	struct termios sys_ti;	struct serial_proxy *prx;	int sk, ret;	sk = open(address, O_RDONLY | O_NOCTTY);	if (sk < 0) {		error("Cant open TTY: %s(%d)", strerror(errno), errno);		return -EINVAL;	}	prx = g_new0(struct serial_proxy, 1);	prx->address = g_strdup(address);	prx->uuid128 = g_strdup(uuid128);	prx->type = TTY_PROXY;	prx->adapter = adapter;	/* Current TTY settings */	memset(&sys_ti, 0, sizeof(sys_ti));	tcgetattr(sk, &sys_ti);	memcpy(&prx->sys_ti, &sys_ti, sizeof(sys_ti));	close(sk);	if (!ti) {		/* Use current settings */		memcpy(&prx->proxy_ti, &sys_ti, sizeof(sys_ti));	} else {		/* New TTY settings: user provided */		memcpy(&prx->proxy_ti, ti, sizeof(*ti));	}	ret = register_proxy_object(prx, outpath, size);	if (ret < 0)		proxy_free(prx);	if (save)		proxy_store(&adapter->src, uuid128, address, NULL,			prx->channel, 0, &prx->proxy_ti);	return ret;}static int proxy_socket_register(struct serial_adapter *adapter,				const char *uuid128, const char *address,				char *outpath, size_t size, gboolean save){	struct serial_proxy *prx;	int ret;	prx = g_new0(struct serial_proxy, 1);	prx->address = g_strdup(address);	prx->uuid128 = g_strdup(uuid128);	prx->type = UNIX_SOCKET_PROXY;	prx->adapter = adapter;	ret = register_proxy_object(prx, outpath, size);	if (ret < 0)		proxy_free(prx);	if (save)		proxy_store(&adapter->src, uuid128, address, NULL,				prx->channel, 0, NULL);	return ret;}static int proxy_tcp_register(struct serial_adapter *adapter,				const char *uuid128, const char *address,				char *outpath, size_t size, gboolean save){	struct serial_proxy *prx;	int ret;	prx = g_new0(struct serial_proxy, 1);	prx->address = g_strdup(address);	prx->uuid128 = g_strdup(uuid128);	prx->type = TCP_SOCKET_PROXY;	prx->adapter = adapter;	ret = register_proxy_object(prx, outpath, size);	if (ret < 0)		proxy_free(prx);	if (save)		proxy_store(&adapter->src, uuid128, address, NULL,				prx->channel, 0, NULL);	return ret;}static proxy_type_t addr2type(const char *address){	struct stat st;	if (stat(address, &st) < 0) {		/*		 * Unix socket: if the sun_path starts with null byte		 * it refers to abstract namespace. 'x00' will be used		 * to represent the null byte.		 */		if (strncmp("localhost:", address, 10) == 0)			return TCP_SOCKET_PROXY;		if (strncmp("x00", address, 3) != 0)			return UNKNOWN_PROXY_TYPE;		else			return UNIX_SOCKET_PROXY;	} else {		/* Filesystem: char device or unix socket */		if (S_ISCHR(st.st_mode) && strncmp("/dev/", address, 4) == 0)			return TTY_PROXY;		else if (S_ISSOCK(st.st_mode))			return UNIX_SOCKET_PROXY;		else			return UNKNOWN_PROXY_TYPE;	}}static int proxy_addrcmp(gconstpointer proxy, gconstpointer addr){	const struct serial_proxy *prx = proxy;	const char *address = addr;	return strcmp(prx->address, address);}static int proxy_pathcmp(gconstpointer proxy, gconstpointer p){	const struct serial_proxy *prx = proxy;	const char *path = p;	return strcmp(prx->path, path);}static DBusMessage *create_proxy(DBusConnection *conn,				DBusMessage *msg, void *data){	struct serial_adapter *adapter = data;	char path[MAX_PATH_LENGTH + 1];	const char *uuid128, *address, *ppath = path;	DBusMessage *reply;	proxy_type_t type;	uuid_t uuid;	int ret;	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &uuid128,				DBUS_TYPE_STRING, &address,				DBUS_TYPE_INVALID))		return NULL;	if (bt_string2uuid(&uuid, uuid128) < 0)		return invalid_arguments(msg, "Invalid UUID");	type = addr2type(address);	if (type == UNKNOWN_PROXY_TYPE)		return invalid_arguments(msg, "Invalid address");	/* Only one proxy per address(TTY or unix socket) is allowed */	if (g_slist_find_custom(adapter->proxies, address, proxy_addrcmp))		return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExist",						"Proxy already exists");	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	switch (type) {	case UNIX_SOCKET_PROXY:		ret = proxy_socket_register(adapter, uuid128, address,						path, sizeof(path), TRUE);		break;	case TTY_PROXY:		ret = proxy_tty_register(adapter, uuid128, address,				NULL, path, sizeof(path), TRUE);		break;	case TCP_SOCKET_PROXY:		ret = proxy_tcp_register(adapter, uuid128, address,					path, sizeof(path), TRUE);		break;	default:		ret = -1;	}	if (ret < 0) {		dbus_message_unref(reply);		return failed(msg, "Create object path failed");	}	g_dbus_emit_signal(adapter->conn, adapter->path,			SERIAL_MANAGER_INTERFACE, "ProxyCreated",			DBUS_TYPE_STRING, &ppath,			DBUS_TYPE_INVALID);	dbus_message_append_args(reply,			DBUS_TYPE_STRING, &ppath,			DBUS_TYPE_INVALID);	return reply;}static DBusMessage *list_proxies(DBusConnection *conn,				DBusMessage *msg, void *data){	struct serial_adapter *adapter = data;	const GSList *l;	DBusMessage *reply;	DBusMessageIter iter, iter_array;	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	dbus_message_iter_init_append(reply, &iter);	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,			DBUS_TYPE_STRING_AS_STRING, &iter_array);	for (l = adapter->proxies; l; l = l->next) {		struct serial_proxy *prx = l->data;		dbus_message_iter_append_basic(&iter_array,				DBUS_TYPE_STRING, &prx->path);	}	dbus_message_iter_close_container(&iter, &iter_array);	return reply;}static DBusMessage *remove_proxy(DBusConnection *conn,				DBusMessage *msg, void *data){	struct serial_adapter *adapter = data;	struct serial_proxy *prx;	const char *path;	GSList *l;	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &path,				DBUS_TYPE_INVALID))		return NULL;	l = g_slist_find_custom(adapter->proxies, path, proxy_pathcmp);	if (!l)		return does_not_exist(msg, "Invalid proxy path");	g_dbus_emit_signal(conn, adapter->path,			SERIAL_MANAGER_INTERFACE, "ProxyRemoved",			DBUS_TYPE_STRING, &path,			DBUS_TYPE_INVALID);	prx = l->data;	proxy_delete(&adapter->src, prx->address);	adapter->proxies = g_slist_remove(adapter->proxies, prx);	g_dbus_unregister_interface(conn, path, SERIAL_PROXY_INTERFACE);	return dbus_message_new_method_return(msg);}static void manager_path_unregister(void *data){	struct serial_adapter *adapter = data;	GSList *l;	/* Remove proxy objects */	for (l = adapter->proxies; l; l = l->next) {		struct serial_proxy *prx = l->data;		char *path = g_strdup(prx->path);		g_dbus_unregister_interface(adapter->conn, path,					SERIAL_PROXY_INTERFACE);		g_free(path);	}	if (adapter->conn)		dbus_connection_unref(adapter->conn);	adapters = g_slist_remove(adapters, adapter);	g_slist_free(adapter->proxies);	g_free(adapter->path);	g_free(adapter);}static GDBusMethodTable manager_methods[] = {	{ "CreateProxy",		"ss",	"s",	create_proxy },	{ "ListProxies",		"",	"as",	list_proxies },	{ "RemoveProxy",		"s",	"",	remove_proxy },	{ },};static GDBusSignalTable manager_signals[] = {	{ "ProxyCreated",		"s"	},	{ "ProxyRemoved",		"s"	},	{ }};static void parse_proxy(char *key, char *value, void *data){	struct serial_adapter *adapter = data;	char uuid128[MAX_LEN_UUID_STR], tmp[3];	char *pvalue;	proxy_type_t type;	int ch, opts, pos;	struct termios ti;	uint8_t *pti;	memset(uuid128, 0, sizeof(uuid128));	ch = opts = pos = 0;	if (sscanf(value,"%s %d 0x%04X %n", uuid128, &ch, &opts, &pos) != 3)		return;	/* Extracting name */	value += pos;	pvalue = strchr(value, ':');	if (!pvalue)		return;	/* FIXME: currently name is not used */	*pvalue = '\0';	type = addr2type(key);	switch (type) {	case TTY_PROXY:		/* Extracting termios */		pvalue++;		if (!pvalue || strlen(pvalue) != (2 * sizeof(ti)))			return;		memset(&ti, 0, sizeof(ti));		memset(tmp, 0, sizeof(tmp));		/* Converting to termios struct */		pti = (uint8_t *) &ti;		for (pos = 0; pos < sizeof(ti); pos++, pvalue += 2, pti++) {			memcpy(tmp, pvalue, 2);			*pti = (uint8_t) strtol(tmp, NULL, 16);		}		proxy_tty_register(adapter, uuid128, key, &ti, NULL, 0, FALSE);		break;	case UNIX_SOCKET_PROXY:		proxy_socket_register(adapter, uuid128, key, NULL, 0, FALSE);		break;	case TCP_SOCKET_PROXY:		proxy_tcp_register(adapter, uuid128, key, NULL, 0, FALSE);		break;	default:		return;	}}static void register_stored(struct serial_adapter *adapter){	char filename[PATH_MAX + 1];	char address[18];	ba2str(&adapter->src, address);	snprintf(filename, PATH_MAX, "%s/%s/proxy", STORAGEDIR, address);	textfile_foreach(filename, parse_proxy, adapter);}static struct serial_adapter *find_adapter(GSList *list, const char *path){	GSList *l;	for (l = list; l; l = l->next) {		struct serial_adapter *adapter = l->data;		if (g_str_equal(adapter->path, path))			return adapter;	}	return NULL;}int proxy_register(DBusConnection *conn, const char *path, bdaddr_t *src){	struct serial_adapter *adapter;	adapter = find_adapter(adapters, path);	if (adapter)		return -EINVAL;	adapter = g_new0(struct serial_adapter, 1);	adapter->conn = dbus_connection_ref(conn);	bacpy(&adapter->src, src);	adapter->path = g_strdup(path);	if (!g_dbus_register_interface(conn, path,					SERIAL_MANAGER_INTERFACE,					manager_methods, manager_signals, NULL,					adapter, manager_path_unregister)) {		error("Failed to register %s interface to %s",				SERIAL_MANAGER_INTERFACE, path);		return -1;	}	register_stored(adapter);	adapters = g_slist_append(adapters, adapter);	info("Registered interface %s on path %s",		SERIAL_MANAGER_INTERFACE, path);	return 0;}void proxy_unregister(const char *path){	struct serial_adapter *adapter;	adapter = find_adapter(adapters, path);	if (!adapter)		return;	g_dbus_unregister_interface(adapter->conn, path,			SERIAL_MANAGER_INTERFACE);}

⌨️ 快捷键说明

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