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>
20 #include <sys/types.h>
32 #include "got_error.h"
35 #include "got_lib_poll.h"
39 const struct got_error
*
40 gotd_imsg_recv_error(uint32_t *client_id
, struct imsg
*imsg
)
42 struct gotd_imsg_error ierr
;
45 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
46 if (datalen
!= sizeof(ierr
))
47 return got_error(GOT_ERR_PRIVSEP_LEN
);
48 memcpy(&ierr
, imsg
->data
, sizeof(ierr
));
51 *client_id
= ierr
.client_id
;
53 if (ierr
.code
== GOT_ERR_ERRNO
)
54 errno
= ierr
.errno_code
;
56 return got_error_msg(ierr
.code
, ierr
.msg
);
59 const struct got_error
*
60 gotd_imsg_flush(struct imsgbuf
*ibuf
)
62 const struct got_error
*err
= NULL
;
64 while (ibuf
->w
.queued
> 0) {
65 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
69 if (imsg_flush(ibuf
) == -1) {
70 if (errno
!= EAGAIN
) {
72 err
= got_error_from_errno("imsg_flush");
81 const struct got_error
*
82 gotd_imsg_recv(struct imsg
*imsg
, struct imsgbuf
*ibuf
, size_t min_datalen
)
86 n
= imsg_get(ibuf
, imsg
);
88 return got_error_from_errno("imsg_get");
94 return got_error(GOT_ERR_PRIVSEP_READ
);
95 return got_error_from_errno("imsg_read");
98 return got_error(GOT_ERR_EOF
);
99 n
= imsg_get(ibuf
, imsg
);
101 return got_error_from_errno("imsg_get");
104 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
)
105 return got_error(GOT_ERR_PRIVSEP_LEN
);
110 const struct got_error
*
111 gotd_imsg_poll_recv(struct imsg
*imsg
, struct imsgbuf
*ibuf
, size_t min_datalen
)
113 const struct got_error
*err
= NULL
;
116 err
= gotd_imsg_recv(imsg
, ibuf
, min_datalen
);
117 if (err
== NULL
|| err
->code
!= GOT_ERR_PRIVSEP_READ
)
120 err
= got_poll_fd(ibuf
->fd
, POLLIN
, INFTIM
);
129 gotd_imsg_send_error(struct imsgbuf
*ibuf
, uint32_t peerid
,
130 uint32_t client_id
, const struct got_error
*err
)
132 const struct got_error
*flush_err
;
133 struct gotd_imsg_error ierr
;
136 ierr
.code
= err
->code
;
137 if (err
->code
== GOT_ERR_ERRNO
)
138 ierr
.errno_code
= errno
;
141 ierr
.client_id
= client_id
;
142 strlcpy(ierr
.msg
, err
->msg
, sizeof(ierr
.msg
));
144 ret
= imsg_compose(ibuf
, GOTD_IMSG_ERROR
, peerid
, getpid(), -1,
145 &ierr
, sizeof(ierr
));
149 flush_err
= gotd_imsg_flush(ibuf
);
157 gotd_imsg_send_error_event(struct gotd_imsgev
*iev
, uint32_t peerid
,
158 uint32_t client_id
, const struct got_error
*err
)
160 struct gotd_imsg_error ierr
;
163 ierr
.code
= err
->code
;
164 if (err
->code
== GOT_ERR_ERRNO
)
165 ierr
.errno_code
= errno
;
168 ierr
.client_id
= client_id
;
169 strlcpy(ierr
.msg
, err
->msg
, sizeof(ierr
.msg
));
171 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_ERROR
, peerid
, -1,
172 &ierr
, sizeof(ierr
));
180 gotd_imsg_event_add(struct gotd_imsgev
*iev
)
182 iev
->events
= EV_READ
;
183 if (iev
->ibuf
.w
.queued
)
184 iev
->events
|= EV_WRITE
;
187 event_set(&iev
->ev
, iev
->ibuf
.fd
, iev
->events
, iev
->handler
, iev
);
188 event_add(&iev
->ev
, NULL
);
192 gotd_imsg_compose_event(struct gotd_imsgev
*iev
, uint16_t type
, uint32_t peerid
,
193 int fd
, void *data
, uint16_t datalen
)
197 ret
= imsg_compose(&iev
->ibuf
, type
, peerid
, getpid(), fd
,
200 gotd_imsg_event_add(iev
);
206 gotd_imsg_forward(struct gotd_imsgev
*iev
, struct imsg
*imsg
, int fd
)
208 return gotd_imsg_compose_event(iev
, imsg
->hdr
.type
, imsg
->hdr
.peerid
,
209 fd
, imsg
->data
, imsg
->hdr
.len
- IMSG_HEADER_SIZE
);