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"
33 #include "got_object.h"
36 #include "got_lib_poll.h"
40 const struct got_error
*
41 gotd_imsg_recv_error(uint32_t *client_id
, struct imsg
*imsg
)
43 struct gotd_imsg_error ierr
;
46 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
47 if (datalen
!= sizeof(ierr
))
48 return got_error(GOT_ERR_PRIVSEP_LEN
);
49 memcpy(&ierr
, imsg
->data
, sizeof(ierr
));
52 *client_id
= ierr
.client_id
;
54 if (ierr
.code
== GOT_ERR_ERRNO
)
55 errno
= ierr
.errno_code
;
57 return got_error_msg(ierr
.code
, ierr
.msg
);
60 const struct got_error
*
61 gotd_imsg_flush(struct imsgbuf
*ibuf
)
63 const struct got_error
*err
= NULL
;
65 while (ibuf
->w
.queued
> 0) {
66 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
70 if (imsg_flush(ibuf
) == -1) {
71 if (errno
!= EAGAIN
) {
73 err
= got_error_from_errno("imsg_flush");
82 const struct got_error
*
83 gotd_imsg_recv(struct imsg
*imsg
, struct imsgbuf
*ibuf
, size_t min_datalen
)
87 n
= imsg_get(ibuf
, imsg
);
89 return got_error_from_errno("imsg_get");
95 return got_error(GOT_ERR_PRIVSEP_READ
);
96 return got_error_from_errno("imsg_read");
99 return got_error(GOT_ERR_EOF
);
100 n
= imsg_get(ibuf
, imsg
);
102 return got_error_from_errno("imsg_get");
105 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
)
106 return got_error(GOT_ERR_PRIVSEP_LEN
);
111 const struct got_error
*
112 gotd_imsg_poll_recv(struct imsg
*imsg
, struct imsgbuf
*ibuf
, size_t min_datalen
)
114 const struct got_error
*err
= NULL
;
117 err
= gotd_imsg_recv(imsg
, ibuf
, min_datalen
);
118 if (err
== NULL
|| err
->code
!= GOT_ERR_PRIVSEP_READ
)
121 err
= got_poll_fd(ibuf
->fd
, POLLIN
, INFTIM
);
130 gotd_imsg_send_error(struct imsgbuf
*ibuf
, uint32_t peerid
,
131 uint32_t client_id
, const struct got_error
*err
)
133 const struct got_error
*flush_err
;
134 struct gotd_imsg_error ierr
;
137 ierr
.code
= err
->code
;
138 if (err
->code
== GOT_ERR_ERRNO
)
139 ierr
.errno_code
= errno
;
142 ierr
.client_id
= client_id
;
143 strlcpy(ierr
.msg
, err
->msg
, sizeof(ierr
.msg
));
145 ret
= imsg_compose(ibuf
, GOTD_IMSG_ERROR
, peerid
, getpid(), -1,
146 &ierr
, sizeof(ierr
));
150 flush_err
= gotd_imsg_flush(ibuf
);
158 gotd_imsg_send_error_event(struct gotd_imsgev
*iev
, uint32_t peerid
,
159 uint32_t client_id
, const struct got_error
*err
)
161 struct gotd_imsg_error ierr
;
164 ierr
.code
= err
->code
;
165 if (err
->code
== GOT_ERR_ERRNO
)
166 ierr
.errno_code
= errno
;
169 ierr
.client_id
= client_id
;
170 strlcpy(ierr
.msg
, err
->msg
, sizeof(ierr
.msg
));
172 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_ERROR
, peerid
, -1,
173 &ierr
, sizeof(ierr
));
181 gotd_imsg_event_add(struct gotd_imsgev
*iev
)
183 iev
->events
= EV_READ
;
184 if (iev
->ibuf
.w
.queued
)
185 iev
->events
|= EV_WRITE
;
188 event_set(&iev
->ev
, iev
->ibuf
.fd
, iev
->events
, iev
->handler
, iev
);
189 event_add(&iev
->ev
, NULL
);
193 gotd_imsg_compose_event(struct gotd_imsgev
*iev
, uint16_t type
, uint32_t peerid
,
194 int fd
, void *data
, uint16_t datalen
)
198 ret
= imsg_compose(&iev
->ibuf
, type
, peerid
, getpid(), fd
,
201 gotd_imsg_event_add(iev
);
207 gotd_imsg_forward(struct gotd_imsgev
*iev
, struct imsg
*imsg
, int fd
)
209 return gotd_imsg_compose_event(iev
, imsg
->hdr
.type
, imsg
->hdr
.peerid
,
210 fd
, imsg
->data
, imsg
->hdr
.len
- IMSG_HEADER_SIZE
);