d30498cdf48b4e8007d4e24a9515c326d4e2d902
[petitboot] / ui / common / discover-client.c
1
2 #include <errno.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <stdint.h>
7
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <asm/byteorder.h>
11
12 #include <talloc/talloc.h>
13 #include <log.h>
14
15 #include "ui/common/discover-client.h"
16 #include "pb-protocol/pb-protocol.h"
17
18 struct discover_client {
19         int fd;
20         struct discover_client_ops ops;
21 };
22
23 static int discover_client_destructor(void *arg)
24 {
25         struct discover_client *client = arg;
26
27         if (client->fd >= 0)
28                 close(client->fd);
29
30         return 0;
31 }
32
33 struct discover_client* discover_client_init(
34         const struct discover_client_ops *ops)
35 {
36         struct discover_client *client;
37         struct sockaddr_un addr;
38
39         client = talloc(NULL, struct discover_client);
40         if (!client)
41                 return NULL;
42
43         memcpy(&client->ops, ops, sizeof(client->ops));
44
45         client->fd = socket(AF_UNIX, SOCK_STREAM, 0);
46         if (!client->fd < 0) {
47                 pb_log("%s: socket: %s\n", __func__, strerror(errno));
48                 goto out_err;
49         }
50
51         talloc_set_destructor(client, discover_client_destructor);
52
53         addr.sun_family = AF_UNIX;
54         strcpy(addr.sun_path, PB_SOCKET_PATH);
55
56         if (connect(client->fd, (struct sockaddr *)&addr, sizeof(addr))) {
57                 pb_log("%s: connect: %s\n", __func__, strerror(errno));
58                 goto out_err;
59         }
60
61         return client;
62
63 out_err:
64         talloc_free(client);
65         return NULL;
66 }
67
68 int discover_client_get_fd(const struct discover_client *client)
69 {
70         return client->fd;
71 }
72
73 void discover_client_destroy(struct discover_client *client)
74 {
75         talloc_free(client);
76 }
77
78 int discover_client_process(struct discover_client *client)
79 {
80         struct pb_protocol_message *message;
81         struct device *dev;
82         char *dev_id;
83
84         message = pb_protocol_read_message(client, client->fd);
85
86         if (!message)
87                 return -1;
88
89         switch (message->action) {
90         case PB_PROTOCOL_ACTION_ADD:
91                 dev = pb_protocol_deserialise_device(client, message);
92                 if (!dev) {
93                         pb_log("%s: no device?\n", __func__);
94                         return 0;
95                 }
96                 client->ops.add_device(dev, client->ops.cb_arg);
97                 talloc_free(dev);
98                 break;
99         case PB_PROTOCOL_ACTION_REMOVE:
100                 dev_id = pb_protocol_deserialise_string(client, message);
101                 if (!dev_id) {
102                         pb_log("%s: no device id?\n", __func__);
103                         return 0;
104                 }
105                 client->ops.remove_device(dev_id, client->ops.cb_arg);
106                 break;
107         default:
108                 pb_log("%s: unknown action %d\n", __func__, message->action);
109         }
110
111
112         return 0;
113 }