2 * Copyright (c) 2022 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "got_compat.h"
19 #include <sys/queue.h>
21 #include <sys/types.h>
33 #include "got_error.h"
34 #include "got_object.h"
37 #include "got_lib_poll.h"
41 const struct got_error
*
42 gotd_imsg_recv_error(uint32_t *client_id
, struct imsg
*imsg
)
44 struct gotd_imsg_error ierr
;
47 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
48 if (datalen
!= sizeof(ierr
))
49 return got_error(GOT_ERR_PRIVSEP_LEN
);
50 memcpy(&ierr
, imsg
->data
, sizeof(ierr
));
53 *client_id
= ierr
.client_id
;
55 if (ierr
.code
== GOT_ERR_ERRNO
)
56 errno
= ierr
.errno_code
;
58 return got_error_msg(ierr
.code
, ierr
.msg
);
61 const struct got_error
*
62 gotd_imsg_flush(struct imsgbuf
*ibuf
)
64 const struct got_error
*err
= NULL
;
66 while (imsgbuf_queuelen(ibuf
) > 0) {
67 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
71 if (imsgbuf_write(ibuf
) == -1) {
72 err
= got_error_from_errno("imsgbuf_write");
80 static const struct got_error
*
81 gotd_imsg_recv(struct imsg
*imsg
, struct imsgbuf
*ibuf
, size_t min_datalen
)
85 n
= imsg_get(ibuf
, imsg
);
87 return got_error_from_errno("imsg_get");
90 n
= imsgbuf_read(ibuf
);
92 return got_error_from_errno("imsgbuf_read");
94 return got_error(GOT_ERR_EOF
);
95 n
= imsg_get(ibuf
, imsg
);
97 return got_error_from_errno("imsg_get");
99 return got_error(GOT_ERR_PRIVSEP_READ
);
102 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
)
103 return got_error(GOT_ERR_PRIVSEP_LEN
);
108 const struct got_error
*
109 gotd_imsg_poll_recv(struct imsg
*imsg
, struct imsgbuf
*ibuf
, size_t min_datalen
)
111 const struct got_error
*err
= NULL
;
114 err
= gotd_imsg_recv(imsg
, ibuf
, min_datalen
);
115 if (err
== NULL
|| err
->code
!= GOT_ERR_PRIVSEP_READ
)
118 err
= got_poll_fd(ibuf
->fd
, POLLIN
, INFTIM
);
127 gotd_imsg_send_error(struct imsgbuf
*ibuf
, uint32_t peerid
,
128 uint32_t client_id
, const struct got_error
*err
)
130 const struct got_error
*flush_err
;
131 struct gotd_imsg_error ierr
;
134 ierr
.code
= err
->code
;
135 if (err
->code
== GOT_ERR_ERRNO
)
136 ierr
.errno_code
= errno
;
139 ierr
.client_id
= client_id
;
140 strlcpy(ierr
.msg
, err
->msg
, sizeof(ierr
.msg
));
142 ret
= imsg_compose(ibuf
, GOTD_IMSG_ERROR
, peerid
, getpid(), -1,
143 &ierr
, sizeof(ierr
));
147 flush_err
= gotd_imsg_flush(ibuf
);
155 gotd_imsg_send_error_event(struct gotd_imsgev
*iev
, uint32_t peerid
,
156 uint32_t client_id
, const struct got_error
*err
)
158 struct gotd_imsg_error ierr
;
161 ierr
.code
= err
->code
;
162 if (err
->code
== GOT_ERR_ERRNO
)
163 ierr
.errno_code
= errno
;
166 ierr
.client_id
= client_id
;
167 strlcpy(ierr
.msg
, err
->msg
, sizeof(ierr
.msg
));
169 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_ERROR
, peerid
, -1,
170 &ierr
, sizeof(ierr
));
178 gotd_imsg_event_add(struct gotd_imsgev
*iev
)
180 iev
->events
= EV_READ
;
181 if (imsgbuf_queuelen(&iev
->ibuf
))
182 iev
->events
|= EV_WRITE
;
185 event_set(&iev
->ev
, iev
->ibuf
.fd
, iev
->events
, iev
->handler
, iev
);
186 event_add(&iev
->ev
, NULL
);
190 gotd_imsg_compose_event(struct gotd_imsgev
*iev
, uint16_t type
, uint32_t peerid
,
191 int fd
, void *data
, uint16_t datalen
)
195 ret
= imsg_compose(&iev
->ibuf
, type
, peerid
, getpid(), fd
,
198 gotd_imsg_event_add(iev
);
204 gotd_imsg_forward(struct gotd_imsgev
*iev
, struct imsg
*imsg
, int fd
)
206 return gotd_imsg_compose_event(iev
, imsg
->hdr
.type
, imsg
->hdr
.peerid
,
207 fd
, imsg
->data
, imsg
->hdr
.len
- IMSG_HEADER_SIZE
);