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
124
125
126
127
128
129
130
131
|
#include "ipc.h"
ipc_sender *setup_ipc_sender(str addr, int backlog){
ipc_sender *is = calloc(1, sizeof(ipc_sender));
is->addr = dup_str(addr);
is->ssocket = socket(AF_UNIX, SOCK_STREAM, 0);
if(is->ssocket == -1){
log_error("%s: socket: %s", __FUNCTION__, strerror(errno));
goto error;
}
struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
memcpy(sockaddr.sun_path, is->addr.ptr, is->addr.len);
sockaddr.sun_path[is->addr.len] = '\0';
unlink(is->addr.ptr);
if(bind(is->ssocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == -1){
log_error("%s: bind: %s", __FUNCTION__, strerror(errno));
goto error;
}
if(listen(is->ssocket, backlog) == -1){
log_error("%s: listen: %s", __FUNCTION__, strerror(errno));
goto error;
}
if(0){
error:
destroy_ipc_sender(&is);
}
return is;
}
void destroy_ipc_sender(ipc_sender **is){
if(*is != NULL){
close((*is)->ssocket);
(*is)->ssocket = -1;
unlink((*is)->addr.ptr);
free_str(&(*is)->addr);
free(*is);
*is = NULL;
}
}
ipc_listener *setup_ipc_listener(str saddr){
ipc_listener *il = calloc(1, sizeof(ipc_listener));
il->saddr = dup_str(saddr);
il->csocket = socket(AF_UNIX, SOCK_STREAM, 0);
if(il->csocket == -1){
log_error("%s: socket: %s", __FUNCTION__, strerror(errno));
goto error;
}
struct sockaddr_un socksaddr = { .sun_family = AF_UNIX };
memcpy(socksaddr.sun_path, il->saddr.ptr, il->saddr.len);
socksaddr.sun_path[il->saddr.len] = '\0';
if(connect(il->csocket, (struct sockaddr *)&socksaddr, sizeof(socksaddr)) == -1){
log_error("%s: connect: %s", __FUNCTION__, strerror(errno));
goto error;
}
if(0){
error:
destroy_ipc_listener(&il);
}
return il;
}
void destroy_ipc_listener(ipc_listener **il){
if(*il != NULL){
close((*il)->csocket);
(*il)->csocket = -1;
free_str(&(*il)->saddr);
free(*il);
*il = NULL;
}
}
int send_ipc_message(int to, ipc_type type, str msg){
if(send(to, &type, sizeof(uint8_t), 0) -1){
log_error("Can't send message type to socket %d: %s", to, strerror(errno));
return 1;
}
msg.len++;
if(send(to, &msg.len, sizeof(msg.len), 0) == -1){
log_error("Can't send message length to socket %d: %s", to, strerror(errno));
return 1;
}
if(send(to, msg.ptr, msg.len, 0) == -1){
log_error("Can't send message to socket %d: %s", to, strerror(errno));
return 1;
}
send(to, 0, 1, 0);
char ack[3];
if(recv(to, ack, 3, 0) == -1){
log_error("Receiving ACK from listener");
return 1;
}
if(strncmp(ack, "ACK", 3) != 0){
log_error("Received '%.3s' from listener instead of 'ACK'", ack);
return 1;
}
return 0;
}
ipc_msg receive_ipc_message(ipc_listener *il){
ipc_msg msg = {0};
if(recv(il->csocket, &msg.type, sizeof(uint8_t), 0) == -1){
log_error("Can't receive message type from socket %d: %s", il->csocket, strerror(errno));
goto end;
}
if(recv(il->csocket, &msg.msg.len, sizeof(msg.msg.len), 0) == -1){
log_error("Can't receive message length from socket %d: %s", il->csocket, strerror(errno));
goto end;
}
msg.msg.cap = msg.msg.len;
msg.msg.ptr = calloc(msg.msg.len, sizeof(char));
if(recv(il->csocket, msg.msg.ptr, msg.msg.len, 0) == -1){
log_error("Can't receive message from socket %d: %s", il->csocket, strerror(errno));
free_ipc_message(&msg);
goto end;
}
end:
if(send(il->csocket, "ACK", slen("ACK"), 0) == -1){
log_error("Sending 'ACK' to sender");
}
return msg;
}
void free_ipc_message(ipc_msg *msg){
msg->type = NONE;
free_str(&msg->msg);
}
|