xref: /aosp_15_r20/external/wmediumd/wmediumd/lib/uds.c (revision 621120a22a0cd8ba80b131fe8bcb37c86ff453e3)
1 /*
2  * Copyright (C) 2019 - 2020 Intel Corporation
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <stddef.h>
7 #include <stdbool.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/un.h>
15 #include <errno.h>
16 #include <usfstl/assert.h>
17 #include <usfstl/loop.h>
18 #include <usfstl/list.h>
19 #include "internal.h"
20 
21 struct usfstl_uds_server {
22 	struct usfstl_loop_entry entry;
23 	void (*connected)(int fd, void *data);
24 	void *data;
25 	char name[];
26 };
27 
usfstl_uds_accept_handler(struct usfstl_loop_entry * entry)28 void usfstl_uds_accept_handler(struct usfstl_loop_entry *entry)
29 {
30 	struct usfstl_uds_server *uds;
31 	int fd;
32 
33 	uds = container_of(entry, struct usfstl_uds_server, entry);
34 	fd = accept(uds->entry.fd, NULL, NULL);
35 
36 	uds->connected(fd, uds->data);
37 }
38 
usfstl_uds_create(const char * path,void (* connected)(int,void *),void * data)39 void usfstl_uds_create(const char *path, void (*connected)(int, void *),
40 		       void *data)
41 {
42 	struct usfstl_uds_server *uds = malloc(sizeof(*uds) + strlen(path) + 1);
43 	struct stat buf;
44 	int ret = stat(path, &buf), fd;
45 	struct sockaddr_un un = {
46 		.sun_family = AF_UNIX,
47 	};
48 
49 	USFSTL_ASSERT(uds);
50 	strcpy(uds->name, path);
51 	uds->data = data;
52 	uds->connected = connected;
53 
54 	if (ret == 0) {
55 		USFSTL_ASSERT_EQ((int)(buf.st_mode & S_IFMT), S_IFSOCK, "%d");
56 		USFSTL_ASSERT_EQ(unlink(path), 0, "%d");
57 	} else {
58 		USFSTL_ASSERT_EQ(errno, ENOENT, "%d");
59 	}
60 
61 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
62 	uds->entry.fd = fd;
63 
64 	strcpy(un.sun_path, path);
65 	USFSTL_ASSERT_EQ(bind(fd, (void *)&un, sizeof(un)), 0, "%d");
66 
67 	USFSTL_ASSERT_EQ(listen(fd, 1000), 0, "%d");
68 
69 	uds->entry.handler = usfstl_uds_accept_handler;
70 
71 	usfstl_loop_register(&uds->entry);
72 }
73 
usfstl_uds_remove(const char * path)74 void usfstl_uds_remove(const char *path)
75 {
76 	struct usfstl_loop_entry *tmp;
77 	struct usfstl_uds_server *uds, *found = NULL;
78 
79 	usfstl_loop_for_each_entry(tmp) {
80 		if (tmp->handler != usfstl_uds_accept_handler)
81 			continue;
82 
83 		uds = container_of(tmp, struct usfstl_uds_server, entry);
84 		if (strcmp(uds->name, path) == 0) {
85 			found = uds;
86 			break;
87 		}
88 	}
89 
90 	USFSTL_ASSERT(found);
91 
92 	close(found->entry.fd);
93 	usfstl_loop_unregister(&found->entry);
94 	unlink(path);
95 	free(found);
96 }
97 
98 struct usfstl_uds_client {
99 	struct usfstl_loop_entry entry;
100 	void (*readable)(int fd, void *data);
101 	void *data;
102 };
103 
usfstl_uds_readable_handler(struct usfstl_loop_entry * entry)104 void usfstl_uds_readable_handler(struct usfstl_loop_entry *entry)
105 {
106 	struct usfstl_uds_client *uds;
107 
108 	uds = container_of(entry, struct usfstl_uds_client, entry);
109 
110 	uds->readable(uds->entry.fd, uds->data);
111 }
112 
usfstl_uds_connect(const char * path,void (* readable)(int,void *),void * data)113 int usfstl_uds_connect(const char *path, void (*readable)(int, void *),
114 		       void *data)
115 {
116 	struct usfstl_uds_client *client;
117 	struct sockaddr_un sock;
118 	int fd, err;
119 
120 	client = calloc(1, sizeof(*client));
121 	USFSTL_ASSERT(client);
122 	client->entry.handler = usfstl_uds_readable_handler;
123 	client->readable = readable;
124 	client->data = data;
125 
126 	sock.sun_family = AF_UNIX;
127 	strcpy(sock.sun_path, path);
128 
129 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
130 	USFSTL_ASSERT(fd >= 0);
131 
132 	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
133 	USFSTL_ASSERT(err == 0);
134 
135 	client->entry.fd = fd;
136 	usfstl_loop_register(&client->entry);
137 
138 	return fd;
139 }
140 
usfstl_uds_disconnect(int fd)141 void usfstl_uds_disconnect(int fd)
142 {
143 	struct usfstl_loop_entry *tmp;
144 	struct usfstl_uds_client *uds, *found = NULL;
145 
146 	usfstl_loop_for_each_entry(tmp) {
147 		if (tmp->handler != usfstl_uds_readable_handler)
148 			continue;
149 
150 		uds = container_of(tmp, struct usfstl_uds_client, entry);
151 		if (uds->entry.fd == fd) {
152 			found = uds;
153 			break;
154 		}
155 	}
156 
157 	USFSTL_ASSERT(found);
158 
159 	close(fd);
160 	usfstl_loop_unregister(&found->entry);
161 	free(found);
162 }
163