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 (imsgbuf_queuelen(ibuf
) > 0) {
66 err
= got_poll_fd(ibuf
->fd
, POLLOUT
, INFTIM
);
70 if (imsgbuf_write(ibuf
) == -1) {
71 err
= got_error_from_errno("imsgbuf_write");
79 static const struct got_error
*
80 gotd_imsg_recv(struct imsg
*imsg
, struct imsgbuf
*ibuf
, size_t min_datalen
)
84 n
= imsg_get(ibuf
, imsg
);
86 return got_error_from_errno("imsg_get");
89 n
= imsgbuf_read(ibuf
);
91 return got_error_from_errno("imsg_read");
93 return got_error(GOT_ERR_EOF
);
94 n
= imsg_get(ibuf
, imsg
);
96 return got_error_from_errno("imsg_get");
98 return got_error(GOT_ERR_PRIVSEP_READ
);
101 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
+ min_datalen
)
102 return got_error(GOT_ERR_PRIVSEP_LEN
);
107 const struct got_error
*
108 gotd_imsg_poll_recv(struct imsg
*imsg
, struct imsgbuf
*ibuf
, size_t min_datalen
)
110 const struct got_error
*err
= NULL
;
113 err
= gotd_imsg_recv(imsg
, ibuf
, min_datalen
);
114 if (err
== NULL
|| err
->code
!= GOT_ERR_PRIVSEP_READ
)
117 err
= got_poll_fd(ibuf
->fd
, POLLIN
, INFTIM
);
126 gotd_imsg_send_error(struct imsgbuf
*ibuf
, uint32_t peerid
,
127 uint32_t client_id
, const struct got_error
*err
)
129 const struct got_error
*flush_err
;
130 struct gotd_imsg_error ierr
;
133 ierr
.code
= err
->code
;
134 if (err
->code
== GOT_ERR_ERRNO
)
135 ierr
.errno_code
= errno
;
138 ierr
.client_id
= client_id
;
139 strlcpy(ierr
.msg
, err
->msg
, sizeof(ierr
.msg
));
141 ret
= imsg_compose(ibuf
, GOTD_IMSG_ERROR
, peerid
, getpid(), -1,
142 &ierr
, sizeof(ierr
));
146 flush_err
= gotd_imsg_flush(ibuf
);
154 gotd_imsg_send_error_event(struct gotd_imsgev
*iev
, uint32_t peerid
,
155 uint32_t client_id
, const struct got_error
*err
)
157 struct gotd_imsg_error ierr
;
160 ierr
.code
= err
->code
;
161 if (err
->code
== GOT_ERR_ERRNO
)
162 ierr
.errno_code
= errno
;
165 ierr
.client_id
= client_id
;
166 strlcpy(ierr
.msg
, err
->msg
, sizeof(ierr
.msg
));
168 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_ERROR
, peerid
, -1,
169 &ierr
, sizeof(ierr
));
177 gotd_imsg_event_add(struct gotd_imsgev
*iev
)
179 iev
->events
= EV_READ
;
180 if (imsgbuf_queuelen(&iev
->ibuf
))
181 iev
->events
|= EV_WRITE
;
184 event_set(&iev
->ev
, iev
->ibuf
.fd
, iev
->events
, iev
->handler
, iev
);
185 event_add(&iev
->ev
, NULL
);
189 gotd_imsg_compose_event(struct gotd_imsgev
*iev
, uint16_t type
, uint32_t peerid
,
190 int fd
, void *data
, uint16_t datalen
)
194 ret
= imsg_compose(&iev
->ibuf
, type
, peerid
, getpid(), fd
,
197 gotd_imsg_event_add(iev
);
203 gotd_imsg_forward(struct gotd_imsgev
*iev
, struct imsg
*imsg
, int fd
)
205 return gotd_imsg_compose_event(iev
, imsg
->hdr
.type
, imsg
->hdr
.peerid
,
206 fd
, imsg
->data
, imsg
->hdr
.len
- IMSG_HEADER_SIZE
);