1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#include "ipc.h"
#include <ctype.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
struct imv_ipc {
int fd;
imv_ipc_callback callback;
void *data;
};
struct connection {
struct imv_ipc *ipc;
int fd;
};
static void *wait_for_commands(void* void_conn)
{
struct connection *conn = void_conn;
while (1) {
char buf[1024];
ssize_t len = recv(conn->fd, buf, sizeof buf - 1, 0);
if (len <= 0) {
break;
}
buf[len] = 0;
while (len > 0 && isspace(buf[len-1])) {
buf[len-1] = 0;
--len;
}
if (conn->ipc->callback) {
conn->ipc->callback(buf, conn->ipc->data);
}
}
close(conn->fd);
free(conn);
return NULL;
}
static void *wait_for_connections(void* void_ipc)
{
struct imv_ipc *ipc = void_ipc;
(void)ipc;
while (1) {
int client = accept(ipc->fd, NULL, NULL);
if (client == -1) {
break;
}
struct connection *conn = calloc(1, sizeof *conn);
conn->ipc = ipc;
conn->fd = client;
pthread_t thread;
pthread_create(&thread, NULL, wait_for_commands, conn);
pthread_detach(thread);
}
return NULL;
}
struct imv_ipc *imv_ipc_create(void)
{
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0) {
return NULL;
}
struct sockaddr_un desc = {
.sun_family = AF_UNIX
};
imv_ipc_path(desc.sun_path, sizeof desc.sun_path, getpid());
unlink(desc.sun_path);
if (bind(sockfd, (struct sockaddr*)&desc, sizeof desc) == -1) {
close(sockfd);
return NULL;
}
if (listen(sockfd, 5) == -1) {
close(sockfd);
return NULL;
}
struct imv_ipc *ipc = calloc(1, sizeof *ipc);
ipc->fd = sockfd;
pthread_t thread;
pthread_create(&thread, NULL, wait_for_connections, ipc);
pthread_detach(thread);
return ipc;
}
void imv_ipc_free(struct imv_ipc *ipc)
{
if (!ipc) {
return;
}
char ipc_filename[1024];
imv_ipc_path(ipc_filename, sizeof ipc_filename, getpid());
unlink(ipc_filename);
close(ipc->fd);
free(ipc);
}
void imv_ipc_set_command_callback(struct imv_ipc *ipc,
imv_ipc_callback callback, void *data)
{
ipc->callback = callback;
ipc->data = data;
}
|