| ipc_us.c | ipc_us.c | |||
|---|---|---|---|---|
| skipping to change at line 22 | skipping to change at line 22 | |||
| * | * | |||
| * libqb is distributed in the hope that it will be useful, | * libqb is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | * GNU Lesser General Public License for more details. | |||
| * | * | |||
| * You should have received a copy of the GNU Lesser General Public License | * You should have received a copy of the GNU Lesser General Public License | |||
| * along with libqb. If not, see <http://www.gnu.org/licenses/>. | * along with libqb. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | */ | |||
| #include "os_base.h" | #include "os_base.h" | |||
| #if defined(HAVE_GETPEERUCRED) | #if defined(HAVE_GETPEERUCRED) | |||
| #include <ucred.h> | #include <ucred.h> | |||
| #endif | #endif | |||
| #ifdef HAVE_SYS_UN_H | #ifdef HAVE_SYS_UN_H | |||
| #include <sys/un.h> | #include <sys/un.h> | |||
| #endif /* HAVE_SYS_UN_H */ | #endif /* HAVE_SYS_UN_H */ | |||
| #ifdef HAVE_SYS_STAT_H | #ifdef HAVE_SYS_STAT_H | |||
| #include <sys/stat.h> | #include <sys/stat.h> | |||
| #endif | #endif | |||
| #ifdef HAVE_SYS_MMAN_H | ||||
| #include <sys/mman.h> | #include <sys/mman.h> | |||
| #endif | ||||
| #include <qb/qbatomic.h> | #include <qb/qbatomic.h> | |||
| #include <qb/qbipcs.h> | #include <qb/qbipcs.h> | |||
| #include <qb/qbloop.h> | #include <qb/qbloop.h> | |||
| #include <qb/qbdefs.h> | #include <qb/qbdefs.h> | |||
| #include "util_int.h" | #include "util_int.h" | |||
| #include "ipc_int.h" | #include "ipc_int.h" | |||
| #define SERVER_BACKLOG 5 | #define SERVER_BACKLOG 5 | |||
| skipping to change at line 69 | skipping to change at line 72 | |||
| struct ipc_auth_ugp { | struct ipc_auth_ugp { | |||
| uid_t uid; | uid_t uid; | |||
| gid_t gid; | gid_t gid; | |||
| pid_t pid; | pid_t pid; | |||
| }; | }; | |||
| static int32_t qb_ipcs_us_connection_acceptor(int fd, int revent, void *dat a); | static int32_t qb_ipcs_us_connection_acceptor(int fd, int revent, void *dat a); | |||
| static int32_t qb_ipc_us_fc_get(struct qb_ipc_one_way *one_way); | static int32_t qb_ipc_us_fc_get(struct qb_ipc_one_way *one_way); | |||
| #ifdef SO_NOSIGPIPE | #ifdef SO_NOSIGPIPE | |||
| static void socket_nosigpipe(int32_t s) | static void | |||
| socket_nosigpipe(int32_t s) | ||||
| { | { | |||
| int32_t on = 1; | int32_t on = 1; | |||
| setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on)); | setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on)); | |||
| } | } | |||
| #endif | #endif | |||
| #ifndef MSG_NOSIGNAL | #ifndef MSG_NOSIGNAL | |||
| #define MSG_NOSIGNAL 0 | #define MSG_NOSIGNAL 0 | |||
| #endif | #endif | |||
| ssize_t qb_ipc_us_send(struct qb_ipc_one_way *one_way, const void *msg, siz | ssize_t | |||
| e_t len) | qb_ipc_us_send(struct qb_ipc_one_way *one_way, const void *msg, size_t len) | |||
| { | { | |||
| int32_t result; | int32_t result; | |||
| struct msghdr msg_send; | struct msghdr msg_send; | |||
| struct iovec iov_send; | struct iovec iov_send; | |||
| char *rbuf = (char *)msg; | char *rbuf = (char *)msg; | |||
| int32_t processed = 0; | int32_t processed = 0; | |||
| struct ipc_us_control *ctl = (struct ipc_us_control *)one_way->u.us. | struct ipc_us_control *ctl = | |||
| shared_data; | (struct ipc_us_control *)one_way->u.us.shared_data; | |||
| msg_send.msg_iov = &iov_send; | msg_send.msg_iov = &iov_send; | |||
| msg_send.msg_iovlen = 1; | msg_send.msg_iovlen = 1; | |||
| msg_send.msg_name = 0; | msg_send.msg_name = 0; | |||
| msg_send.msg_namelen = 0; | msg_send.msg_namelen = 0; | |||
| #if !defined(QB_SOLARIS) | #if !defined(QB_SOLARIS) | |||
| msg_send.msg_control = 0; | msg_send.msg_control = 0; | |||
| msg_send.msg_controllen = 0; | msg_send.msg_controllen = 0; | |||
| msg_send.msg_flags = 0; | msg_send.msg_flags = 0; | |||
| skipping to change at line 122 | skipping to change at line 128 | |||
| processed += result; | processed += result; | |||
| if (processed != len) { | if (processed != len) { | |||
| goto retry_send; | goto retry_send; | |||
| } | } | |||
| if (ctl) { | if (ctl) { | |||
| qb_atomic_int_inc(&ctl->sent); | qb_atomic_int_inc(&ctl->sent); | |||
| } | } | |||
| return processed; | return processed; | |||
| } | } | |||
| static ssize_t qb_ipc_us_sendv(struct qb_ipc_one_way *one_way, const struct | static ssize_t | |||
| iovec *iov, size_t iov_len) | qb_ipc_us_sendv(struct qb_ipc_one_way *one_way, const struct iovec *iov, | |||
| size_t iov_len) | ||||
| { | { | |||
| int32_t result; | int32_t result; | |||
| struct msghdr msg_send; | struct msghdr msg_send; | |||
| int32_t processed = 0; | int32_t processed = 0; | |||
| size_t len = 0; | size_t len = 0; | |||
| int32_t i; | int32_t i; | |||
| struct ipc_us_control *ctl = (struct ipc_us_control *)one_way->u.us. | struct ipc_us_control *ctl = | |||
| shared_data; | (struct ipc_us_control *)one_way->u.us.shared_data; | |||
| for (i = 0; i < iov_len; i++) { | for (i = 0; i < iov_len; i++) { | |||
| len += iov[i].iov_len; | len += iov[i].iov_len; | |||
| } | } | |||
| msg_send.msg_iov = (struct iovec*)iov; | msg_send.msg_iov = (struct iovec *)iov; | |||
| msg_send.msg_iovlen = iov_len; | msg_send.msg_iovlen = iov_len; | |||
| msg_send.msg_name = 0; | msg_send.msg_name = 0; | |||
| msg_send.msg_namelen = 0; | msg_send.msg_namelen = 0; | |||
| #if !defined(QB_SOLARIS) | #if !defined(QB_SOLARIS) | |||
| msg_send.msg_control = 0; | msg_send.msg_control = 0; | |||
| msg_send.msg_controllen = 0; | msg_send.msg_controllen = 0; | |||
| msg_send.msg_flags = 0; | msg_send.msg_flags = 0; | |||
| #else | #else | |||
| msg_send.msg_accrights = NULL; | msg_send.msg_accrights = NULL; | |||
| skipping to change at line 164 | skipping to change at line 173 | |||
| processed += result; | processed += result; | |||
| if (processed != len) { | if (processed != len) { | |||
| goto retry_send; | goto retry_send; | |||
| } | } | |||
| if (ctl) { | if (ctl) { | |||
| qb_atomic_int_inc(&ctl->sent); | qb_atomic_int_inc(&ctl->sent); | |||
| } | } | |||
| return processed; | return processed; | |||
| } | } | |||
| static ssize_t qb_ipc_us_recv_msghdr(int32_t s, | static ssize_t | |||
| struct msghdr *hdr, | qb_ipc_us_recv_msghdr(int32_t s, struct msghdr *hdr, char *msg, size_t len) | |||
| char *msg, size_t len) | ||||
| { | { | |||
| int32_t result; | int32_t result; | |||
| int32_t processed = 0; | int32_t processed = 0; | |||
| retry_recv: | retry_recv: | |||
| hdr->msg_iov->iov_base = &msg[processed]; | hdr->msg_iov->iov_base = &msg[processed]; | |||
| hdr->msg_iov->iov_len = len - processed; | hdr->msg_iov->iov_len = len - processed; | |||
| result = recvmsg(s, hdr, MSG_NOSIGNAL | MSG_WAITALL); | result = recvmsg(s, hdr, MSG_NOSIGNAL | MSG_WAITALL); | |||
| if (result == -1 && errno == EAGAIN) { | if (result == -1 && errno == EAGAIN) { | |||
| skipping to change at line 200 | skipping to change at line 208 | |||
| processed += result; | processed += result; | |||
| if (processed != len) { | if (processed != len) { | |||
| goto retry_recv; | goto retry_recv; | |||
| } | } | |||
| assert(processed == len); | assert(processed == len); | |||
| return processed; | return processed; | |||
| } | } | |||
| int32_t qb_ipc_us_recv_ready(struct qb_ipc_one_way *one_way, int32_t ms_tim | int32_t | |||
| eout) | qb_ipc_us_recv_ready(struct qb_ipc_one_way * one_way, int32_t ms_timeout) | |||
| { | { | |||
| struct pollfd ufds; | struct pollfd ufds; | |||
| int32_t poll_events; | int32_t poll_events; | |||
| ufds.fd = one_way->u.us.sock; | ufds.fd = one_way->u.us.sock; | |||
| ufds.events = POLLIN; | ufds.events = POLLIN; | |||
| ufds.revents = 0; | ufds.revents = 0; | |||
| poll_events = poll (&ufds, 1, ms_timeout); | poll_events = poll(&ufds, 1, ms_timeout); | |||
| if ((poll_events == -1 && errno == EINTR) || | if ((poll_events == -1 && errno == EINTR) || poll_events == 0) { | |||
| poll_events == 0) { | ||||
| return -EAGAIN; | return -EAGAIN; | |||
| } else if (poll_events == -1) { | } else if (poll_events == -1) { | |||
| return -errno; | return -errno; | |||
| } else if (poll_events == 1 && (ufds.revents & (POLLERR|POLLHUP))) { | } else if (poll_events == 1 && (ufds.revents & (POLLERR | POLLHUP))) { | |||
| return -ENOTCONN; | return -ENOTCONN; | |||
| } | } | |||
| return 0; | return 0; | |||
| } | } | |||
| ssize_t qb_ipc_us_recv(struct qb_ipc_one_way *one_way, | ssize_t | |||
| void *msg, size_t len, int32_t timeout) | qb_ipc_us_recv(struct qb_ipc_one_way * one_way, | |||
| void *msg, size_t len, int32_t timeout) | ||||
| { | { | |||
| int32_t result; | int32_t result; | |||
| struct ipc_us_control *ctl = (struct ipc_us_control *)one_way->u.us. | struct ipc_us_control *ctl = | |||
| shared_data; | (struct ipc_us_control *)one_way->u.us.shared_data; | |||
| retry_recv: | retry_recv: | |||
| result = recv(one_way->u.us.sock, msg, len, MSG_NOSIGNAL | MSG_WAITA LL); | result = recv(one_way->u.us.sock, msg, len, MSG_NOSIGNAL | MSG_WAITA LL); | |||
| if (timeout == -1 && result == -1 && errno == EAGAIN) { | if (timeout == -1 && result == -1 && errno == EAGAIN) { | |||
| goto retry_recv; | goto retry_recv; | |||
| } | } | |||
| if (result == -1) { | if (result == -1) { | |||
| return -errno; | return -errno; | |||
| } | } | |||
| if (result == 0) { | if (result == 0) { | |||
| return -ENOTCONN; | return -ENOTCONN; | |||
| } | } | |||
| if (ctl) { | if (ctl) { | |||
| (void)qb_atomic_int_dec_and_test(&ctl->sent); | (void)qb_atomic_int_dec_and_test(&ctl->sent); | |||
| } | } | |||
| return result; | return result; | |||
| } | } | |||
| static int32_t qb_ipcc_us_sock_connect(const char *socket_name, int32_t * s | static int32_t | |||
| ock_pt) | qb_ipcc_us_sock_connect(const char *socket_name, int32_t * sock_pt) | |||
| { | { | |||
| int32_t request_fd; | int32_t request_fd; | |||
| struct sockaddr_un address; | struct sockaddr_un address; | |||
| int32_t res = 0; | int32_t res = 0; | |||
| #if defined(QB_SOLARIS) | #if defined(QB_SOLARIS) | |||
| request_fd = socket(PF_UNIX, SOCK_STREAM, 0); | request_fd = socket(PF_UNIX, SOCK_STREAM, 0); | |||
| #else | #else | |||
| request_fd = socket(PF_LOCAL, SOCK_STREAM, 0); | request_fd = socket(PF_LOCAL, SOCK_STREAM, 0); | |||
| #endif | #endif | |||
| if (request_fd == -1) { | if (request_fd == -1) { | |||
| return -errno; | return -errno; | |||
| } | } | |||
| #ifdef SO_NOSIGPIPE | #ifdef SO_NOSIGPIPE | |||
| socket_nosigpipe(request_fd); | socket_nosigpipe(request_fd); | |||
| #endif /* SO_NOSIGPIPE */ | #endif /* SO_NOSIGPIPE */ | |||
| res = qb_util_fd_nonblock_cloexec_set(request_fd); | res = qb_sys_fd_nonblock_cloexec_set(request_fd); | |||
| if (res < 0) { | if (res < 0) { | |||
| goto error_connect; | goto error_connect; | |||
| } | } | |||
| memset(&address, 0, sizeof(struct sockaddr_un)); | memset(&address, 0, sizeof(struct sockaddr_un)); | |||
| address.sun_family = AF_UNIX; | address.sun_family = AF_UNIX; | |||
| #if defined(QB_BSD) || defined(QB_DARWIN) | #if defined(QB_BSD) || defined(QB_DARWIN) | |||
| address.sun_len = SUN_LEN(&address); | address.sun_len = SUN_LEN(&address); | |||
| #endif | #endif | |||
| #if defined(QB_LINUX) | #if defined(QB_LINUX) | |||
| snprintf(address.sun_path + 1, UNIX_PATH_MAX-1, "%s", socket_name); | snprintf(address.sun_path + 1, UNIX_PATH_MAX - 1, "%s", socket_name) ; | |||
| #else | #else | |||
| snprintf(address.sun_path, UNIX_PATH_MAX, "%s/%s", SOCKETDIR, socket | snprintf(address.sun_path, UNIX_PATH_MAX, "%s/%s", SOCKETDIR, | |||
| _name); | socket_name); | |||
| #endif | #endif | |||
| if (connect(request_fd, (struct sockaddr *)&address, | if (connect(request_fd, (struct sockaddr *)&address, | |||
| QB_SUN_LEN(&address)) == -1) { | QB_SUN_LEN(&address)) == -1) { | |||
| res = -errno; | res = -errno; | |||
| goto error_connect; | goto error_connect; | |||
| } | } | |||
| *sock_pt = request_fd; | *sock_pt = request_fd; | |||
| return 0; | return 0; | |||
| error_connect: | error_connect: | |||
| close(request_fd); | close(request_fd); | |||
| *sock_pt = -1; | *sock_pt = -1; | |||
| return res; | return res; | |||
| } | } | |||
| void qb_ipcc_us_sock_close(int32_t sock) | void | |||
| qb_ipcc_us_sock_close(int32_t sock) | ||||
| { | { | |||
| shutdown(sock, SHUT_RDWR); | shutdown(sock, SHUT_RDWR); | |||
| close(sock); | close(sock); | |||
| } | } | |||
| int32_t qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c, | int32_t | |||
| struct qb_ipc_connection_response *r) | qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c, | |||
| struct qb_ipc_connection_response *r) | ||||
| { | { | |||
| int32_t res; | int32_t res; | |||
| struct qb_ipc_connection_request request; | struct qb_ipc_connection_request request; | |||
| res = qb_ipcc_us_sock_connect(c->name, &c->setup.u.us.sock); | res = qb_ipcc_us_sock_connect(c->name, &c->setup.u.us.sock); | |||
| if (res != 0) { | if (res != 0) { | |||
| return res; | return res; | |||
| } | } | |||
| request.hdr.id = QB_IPC_MSG_AUTHENTICATE; | request.hdr.id = QB_IPC_MSG_AUTHENTICATE; | |||
| request.hdr.size = sizeof(request); | request.hdr.size = sizeof(request); | |||
| request.max_msg_size = c->setup.max_msg_size; | request.max_msg_size = c->setup.max_msg_size; | |||
| res = qb_ipc_us_send(&c->setup, &request, request.hdr.size); | res = qb_ipc_us_send(&c->setup, &request, request.hdr.size); | |||
| if (res < 0) { | if (res < 0) { | |||
| qb_ipcc_us_sock_close(c->setup.u.us.sock); | qb_ipcc_us_sock_close(c->setup.u.us.sock); | |||
| return res; | return res; | |||
| } | } | |||
| res = qb_ipc_us_recv(&c->setup, r, sizeof(struct qb_ipc_connection_r | res = | |||
| esponse), -1); | qb_ipc_us_recv(&c->setup, r, | |||
| sizeof(struct qb_ipc_connection_response), -1); | ||||
| if (res < 0) { | if (res < 0) { | |||
| return res; | return res; | |||
| } | } | |||
| if (r->hdr.error != 0) { | if (r->hdr.error != 0) { | |||
| return r->hdr.error; | return r->hdr.error; | |||
| } | } | |||
| return 0; | return 0; | |||
| } | } | |||
| static void qb_ipcc_us_disconnect(struct qb_ipcc_connection* c) | static void | |||
| qb_ipcc_us_disconnect(struct qb_ipcc_connection *c) | ||||
| { | { | |||
| munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control)); | munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control)); | |||
| unlink(c->request.u.us.shared_file_name); | unlink(c->request.u.us.shared_file_name); | |||
| close(c->request.u.us.sock); | close(c->request.u.us.sock); | |||
| close(c->event.u.us.sock); | close(c->event.u.us.sock); | |||
| } | } | |||
| int32_t qb_ipcc_us_connect(struct qb_ipcc_connection *c, | int32_t | |||
| struct qb_ipc_connection_response *r) | qb_ipcc_us_connect(struct qb_ipcc_connection *c, | |||
| struct qb_ipc_connection_response *r) | ||||
| { | { | |||
| int32_t res; | int32_t res; | |||
| struct qb_ipc_event_connection_request request; | struct qb_ipc_event_connection_request request; | |||
| char path[PATH_MAX]; | char path[PATH_MAX]; | |||
| int32_t fd_hdr; | int32_t fd_hdr; | |||
| struct ipc_us_control * ctl; | struct ipc_us_control *ctl; | |||
| c->needs_sock_for_poll = QB_FALSE; | c->needs_sock_for_poll = QB_FALSE; | |||
| c->funcs.send = qb_ipc_us_send; | c->funcs.send = qb_ipc_us_send; | |||
| c->funcs.sendv = qb_ipc_us_sendv; | c->funcs.sendv = qb_ipc_us_sendv; | |||
| c->funcs.recv = qb_ipc_us_recv; | c->funcs.recv = qb_ipc_us_recv; | |||
| c->funcs.fc_get = qb_ipc_us_fc_get; | c->funcs.fc_get = qb_ipc_us_fc_get; | |||
| c->funcs.disconnect = qb_ipcc_us_disconnect; | c->funcs.disconnect = qb_ipcc_us_disconnect; | |||
| c->request.u.us.sock = c->setup.u.us.sock; | c->request.u.us.sock = c->setup.u.us.sock; | |||
| c->response.u.us.sock = c->setup.u.us.sock; | c->response.u.us.sock = c->setup.u.us.sock; | |||
| c->setup.u.us.sock = -1; | c->setup.u.us.sock = -1; | |||
| fd_hdr = qb_util_mmap_file_open(path, r->request, | fd_hdr = qb_sys_mmap_file_open(path, r->request, | |||
| sizeof(struct ipc_us_control), | sizeof(struct ipc_us_control), O_RDWR | |||
| O_RDWR); | ); | |||
| if (fd_hdr < 0) { | if (fd_hdr < 0) { | |||
| res = -errno; | res = -errno; | |||
| qb_util_log(LOG_ERR, "couldn't open file for mmap: %s", | qb_util_perror(LOG_ERR, "couldn't open file for mmap"); | |||
| strerror(-res)); | ||||
| return res; | return res; | |||
| } | } | |||
| strcpy(c->request.u.us.shared_file_name, r->request); | strcpy(c->request.u.us.shared_file_name, r->request); | |||
| c->request.u.us.shared_data = mmap(0, | c->request.u.us.shared_data = mmap(0, | |||
| sizeof(struct ipc_us_control), | sizeof(struct ipc_us_control), | |||
| PROT_READ | PROT_WRITE, MAP_SHARE D, | PROT_READ | PROT_WRITE, MAP_SHARE D, | |||
| fd_hdr, 0); | fd_hdr, 0); | |||
| if (c->request.u.us.shared_data == MAP_FAILED) { | if (c->request.u.us.shared_data == MAP_FAILED) { | |||
| res = -errno; | res = -errno; | |||
| qb_util_log(LOG_ERR, "couldn't create mmap for header"); | qb_util_perror(LOG_ERR, "couldn't create mmap for header"); | |||
| goto cleanup_hdr; | goto cleanup_hdr; | |||
| } | } | |||
| ctl = (struct ipc_us_control *)c->request.u.us.shared_data; | ctl = (struct ipc_us_control *)c->request.u.us.shared_data; | |||
| ctl->sent = 0; | ctl->sent = 0; | |||
| ctl->flow_control = 0; | ctl->flow_control = 0; | |||
| close(fd_hdr); | close(fd_hdr); | |||
| res = qb_ipcc_us_sock_connect(c->name, &c->event.u.us.sock); | res = qb_ipcc_us_sock_connect(c->name, &c->event.u.us.sock); | |||
| skipping to change at line 414 | skipping to change at line 430 | |||
| unlink(r->request); | unlink(r->request); | |||
| munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control)); | munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control)); | |||
| return res; | return res; | |||
| } | } | |||
| /* | /* | |||
| ************************************************************************** | ************************************************************************** | |||
| * SERVER | * SERVER | |||
| */ | */ | |||
| int32_t qb_ipcs_us_publish(struct qb_ipcs_service * s) | int32_t | |||
| qb_ipcs_us_publish(struct qb_ipcs_service * s) | ||||
| { | { | |||
| struct sockaddr_un un_addr; | struct sockaddr_un un_addr; | |||
| int32_t res; | int32_t res; | |||
| char error_str[100]; | ||||
| /* | /* | |||
| * Create socket for IPC clients, name socket, listen for connection s | * Create socket for IPC clients, name socket, listen for connection s | |||
| */ | */ | |||
| #if defined(QB_SOLARIS) | #if defined(QB_SOLARIS) | |||
| s->server_sock = socket(PF_UNIX, SOCK_STREAM, 0); | s->server_sock = socket(PF_UNIX, SOCK_STREAM, 0); | |||
| #else | #else | |||
| s->server_sock = socket(PF_LOCAL, SOCK_STREAM, 0); | s->server_sock = socket(PF_LOCAL, SOCK_STREAM, 0); | |||
| #endif | #endif | |||
| if (s->server_sock == -1) { | if (s->server_sock == -1) { | |||
| res = -errno; | res = -errno; | |||
| strerror_r(errno, error_str, 100); | qb_util_perror(LOG_ERR, "Cannot create server socket"); | |||
| qb_util_log(LOG_ERR, | ||||
| "Cannot create server socket: %s", error_str); | ||||
| return res; | return res; | |||
| } | } | |||
| res = qb_util_fd_nonblock_cloexec_set(s->server_sock); | res = qb_sys_fd_nonblock_cloexec_set(s->server_sock); | |||
| if (res < 0) { | if (res < 0) { | |||
| goto error_close; | goto error_close; | |||
| } | } | |||
| memset(&un_addr, 0, sizeof(struct sockaddr_un)); | memset(&un_addr, 0, sizeof(struct sockaddr_un)); | |||
| un_addr.sun_family = AF_UNIX; | un_addr.sun_family = AF_UNIX; | |||
| #if defined(QB_BSD) || defined(QB_DARWIN) | #if defined(QB_BSD) || defined(QB_DARWIN) | |||
| un_addr.sun_len = SUN_LEN(&un_addr); | un_addr.sun_len = SUN_LEN(&un_addr); | |||
| #endif | #endif | |||
| qb_util_log(LOG_INFO, "server name: %s", s->name); | qb_util_log(LOG_INFO, "server name: %s", s->name); | |||
| #if defined(QB_LINUX) | #if defined(QB_LINUX) | |||
| snprintf(un_addr.sun_path + 1, UNIX_PATH_MAX-1, "%s", s->name); | snprintf(un_addr.sun_path + 1, UNIX_PATH_MAX - 1, "%s", s->name); | |||
| #else | #else | |||
| { | { | |||
| struct stat stat_out; | struct stat stat_out; | |||
| res = stat(SOCKETDIR, &stat_out); | res = stat(SOCKETDIR, &stat_out); | |||
| if (res == -1 || (res == 0 && !S_ISDIR(stat_out.st_mode))) { | if (res == -1 || (res == 0 && !S_ISDIR(stat_out.st_mode))) { | |||
| res = -errno; | res = -errno; | |||
| qb_util_log(LOG_CRIT, | qb_util_log(LOG_CRIT, | |||
| "Required directory not present %s", | "Required directory not present %s", | |||
| SOCKETDIR); | SOCKETDIR); | |||
| goto error_close; | goto error_close; | |||
| } | } | |||
| snprintf(un_addr.sun_path, UNIX_PATH_MAX, "%s/%s", SOCKETDIR | snprintf(un_addr.sun_path, UNIX_PATH_MAX, "%s/%s", SOCKETDIR | |||
| , s->name); | , | |||
| s->name); | ||||
| unlink(un_addr.sun_path); | unlink(un_addr.sun_path); | |||
| } | } | |||
| #endif | #endif | |||
| res = | res = bind(s->server_sock, (struct sockaddr *)&un_addr, | |||
| bind(s->server_sock, (struct sockaddr *)&un_addr, | QB_SUN_LEN(&un_addr)); | |||
| QB_SUN_LEN(&un_addr)); | ||||
| if (res) { | if (res) { | |||
| res = -errno; | res = -errno; | |||
| strerror_r(errno, error_str, 100); | qb_util_perror(LOG_ERR, "Could not bind AF_UNIX (%s)", | |||
| qb_util_log(LOG_CRIT, | un_addr.sun_path); | |||
| "Could not bind AF_UNIX (%s): %s.", | ||||
| un_addr.sun_path, error_str); | ||||
| goto error_close; | goto error_close; | |||
| } | } | |||
| /* | /* | |||
| * Allow eveyrone to write to the socket since the IPC layer handles | * Allow everyone to write to the socket since the IPC layer handles | |||
| * security automatically | * security automatically | |||
| */ | */ | |||
| #if !defined(QB_LINUX) | #if !defined(QB_LINUX) | |||
| res = chmod(un_addr.sun_path, S_IRWXU | S_IRWXG | S_IRWXO); | res = chmod(un_addr.sun_path, S_IRWXU | S_IRWXG | S_IRWXO); | |||
| #endif | #endif | |||
| if (listen(s->server_sock, SERVER_BACKLOG) == -1) { | if (listen(s->server_sock, SERVER_BACKLOG) == -1) { | |||
| strerror_r(errno, error_str, 100); | qb_util_perror(LOG_ERR, "socket listen failed"); | |||
| qb_util_log(LOG_ERR, "listen failed: %s.", error_str); | ||||
| } | } | |||
| res = s->poll_fns.dispatch_add(s->poll_priority, s->server_sock, | res = s->poll_fns.dispatch_add(s->poll_priority, s->server_sock, | |||
| POLLIN | POLLPRI | POLLNVAL, | POLLIN | POLLPRI | POLLNVAL, | |||
| s, qb_ipcs_us_connection_acceptor); | s, qb_ipcs_us_connection_acceptor); | |||
| return res; | return res; | |||
| error_close: | error_close: | |||
| close(s->server_sock); | close(s->server_sock); | |||
| return res; | return res; | |||
| } | } | |||
| int32_t qb_ipcs_us_withdraw(struct qb_ipcs_service * s) | int32_t | |||
| qb_ipcs_us_withdraw(struct qb_ipcs_service * s) | ||||
| { | { | |||
| qb_util_log(LOG_INFO, "withdrawing server sockets"); | qb_util_log(LOG_INFO, "withdrawing server sockets"); | |||
| shutdown(s->server_sock, SHUT_RDWR); | shutdown(s->server_sock, SHUT_RDWR); | |||
| close(s->server_sock); | close(s->server_sock); | |||
| return 0; | return 0; | |||
| } | } | |||
| static int32_t handle_new_connection(struct qb_ipcs_service *s, | static int32_t | |||
| int32_t auth_result, | handle_new_connection(struct qb_ipcs_service *s, | |||
| int32_t sock, | int32_t auth_result, | |||
| void *msg, size_t len, | int32_t sock, | |||
| struct ipc_auth_ugp *ugp) | void *msg, size_t len, struct ipc_auth_ugp *ugp) | |||
| { | { | |||
| struct qb_ipcs_connection *c = NULL; | struct qb_ipcs_connection *c = NULL; | |||
| struct qb_ipc_connection_request *req = msg; | struct qb_ipc_connection_request *req = msg; | |||
| int32_t res = auth_result; | int32_t res = auth_result; | |||
| int32_t res2 = 0; | ||||
| struct qb_ipc_connection_response response; | struct qb_ipc_connection_response response; | |||
| if (res != 0) { | c = qb_ipcs_connection_alloc(s); | |||
| goto send_response; | if (c == NULL) { | |||
| qb_ipcc_us_sock_close(sock); | ||||
| return -ENOMEM; | ||||
| } | } | |||
| c = qb_ipcs_connection_alloc(s); | c->receive_buf = malloc(req->max_msg_size); | |||
| if (c->receive_buf == NULL) { | ||||
| free(c); | ||||
| qb_ipcc_us_sock_close(sock); | ||||
| return -ENOMEM; | ||||
| } | ||||
| c->setup.u.us.sock = sock; | c->setup.u.us.sock = sock; | |||
| c->request.max_msg_size = req->max_msg_size; | c->request.max_msg_size = req->max_msg_size; | |||
| c->response.max_msg_size = req->max_msg_size; | c->response.max_msg_size = req->max_msg_size; | |||
| c->event.max_msg_size = req->max_msg_size; | c->event.max_msg_size = req->max_msg_size; | |||
| c->pid = ugp->pid; | c->pid = ugp->pid; | |||
| c->euid = ugp->uid; | c->euid = ugp->uid; | |||
| c->egid = ugp->gid; | c->egid = ugp->gid; | |||
| c->stats.client_pid = ugp->pid; | c->stats.client_pid = ugp->pid; | |||
| if (c->service->serv_fns.connection_accept) { | if (auth_result == 0 && c->service->serv_fns.connection_accept) { | |||
| res = c->service->serv_fns.connection_accept(c, | res = c->service->serv_fns.connection_accept(c, | |||
| c->euid, | c->euid, c->egi | |||
| c->egid); | d); | |||
| } | } | |||
| if (res != 0) { | if (res != 0) { | |||
| goto send_response; | goto send_response; | |||
| } | } | |||
| qb_util_log(LOG_INFO, "IPC credentials authenticated"); | qb_util_log(LOG_INFO, "IPC credentials authenticated"); | |||
| memset(&response, 0, sizeof(response)); | memset(&response, 0, sizeof(response)); | |||
| if (s->funcs.connect) { | if (s->funcs.connect) { | |||
| res = s->funcs.connect(s, c, &response); | res = s->funcs.connect(s, c, &response); | |||
| if (res != 0) { | if (res != 0) { | |||
| goto send_response; | goto send_response; | |||
| } | } | |||
| } | } | |||
| /* | ||||
| * The connection is good, add it to the active connection list | ||||
| */ | ||||
| c->state = QB_IPCS_CONNECTION_ACTIVE; | c->state = QB_IPCS_CONNECTION_ACTIVE; | |||
| qb_list_add(&c->list, &s->connections); | qb_list_add(&c->list, &s->connections); | |||
| c->receive_buf = malloc(c->request.max_msg_size); | ||||
| if (s->needs_sock_for_poll) { | if (s->needs_sock_for_poll) { | |||
| qb_ipcs_connection_ref(c); | qb_ipcs_connection_ref(c); | |||
| res = s->poll_fns.dispatch_add(s->poll_priority, | res = s->poll_fns.dispatch_add(s->poll_priority, | |||
| c->setup.u.us.sock, | c->setup.u.us.sock, | |||
| POLLIN | POLLPRI | POLLNVAL, | POLLIN | POLLPRI | POLLNVAL, | |||
| c, | c, | |||
| qb_ipcs_dispatch_connection_r equest); | qb_ipcs_dispatch_connection_r equest); | |||
| } | } | |||
| if (s->type == QB_IPC_SOCKET) { | if (s->type == QB_IPC_SOCKET) { | |||
| c->request.u.us.sock = c->setup.u.us.sock; | c->request.u.us.sock = c->setup.u.us.sock; | |||
| c->response.u.us.sock = c->setup.u.us.sock; | c->response.u.us.sock = c->setup.u.us.sock; | |||
| res = s->poll_fns.dispatch_add(s->poll_priority, | res = s->poll_fns.dispatch_add(s->poll_priority, | |||
| c->request.u.us.sock, | c->request.u.us.sock, | |||
| POLLIN | POLLPRI | POLLNVAL, | POLLIN | POLLPRI | POLLNVAL, | |||
| c, | c, | |||
| qb_ipcs_dispatch_connection_r equest); | qb_ipcs_dispatch_connection_r equest); | |||
| if (res < 0) { | if (res < 0) { | |||
| qb_util_log(LOG_ERR, "Error adding socket to mainloo | qb_util_log(LOG_ERR, | |||
| p."); | "Error adding socket to mainloop."); | |||
| } | } | |||
| } | } | |||
| send_response: | send_response: | |||
| response.hdr.id = QB_IPC_MSG_AUTHENTICATE; | response.hdr.id = QB_IPC_MSG_AUTHENTICATE; | |||
| response.hdr.size = sizeof(response); | response.hdr.size = sizeof(response); | |||
| response.hdr.error = res; | response.hdr.error = res; | |||
| if (res == 0) { | if (res == 0) { | |||
| response.connection = (intptr_t)c; | response.connection = (intptr_t) c; | |||
| response.connection_type = s->type; | response.connection_type = s->type; | |||
| response.max_msg_size = c->request.max_msg_size; | response.max_msg_size = c->request.max_msg_size; | |||
| s->stats.active_connections++; | s->stats.active_connections++; | |||
| } | } | |||
| res = qb_ipc_us_send(&c->setup, &response, response.hdr.size); | res2 = qb_ipc_us_send(&c->setup, &response, response.hdr.size); | |||
| if (res == response.hdr.size) { | if (res == 0 && res2 != response.hdr.size) { | |||
| res = 0; | res = res2; | |||
| } | ||||
| if (res < 0) { | ||||
| qb_util_log(LOG_ERR, "Error sending connection response: %s" | ||||
| , | ||||
| strerror(-res)); | ||||
| } | } | |||
| if (res == 0) { | if (res == 0) { | |||
| if (s->serv_fns.connection_created) { | if (s->serv_fns.connection_created) { | |||
| s->serv_fns.connection_created(c); | s->serv_fns.connection_created(c); | |||
| } | } | |||
| } else if (res == -EACCES) { | c->state = QB_IPCS_CONNECTION_ESTABLISHED; | |||
| qb_util_log(LOG_ERR, "Invalid IPC credentials."); | ||||
| } else { | } else { | |||
| qb_util_log(LOG_ERR, "Error in connection setup: %s.", | if (res == -EACCES) { | |||
| strerror(-res)); | qb_util_log(LOG_ERR, "Invalid IPC credentials."); | |||
| } | } else { | |||
| if (res != 0 && c) { | qb_util_perror(LOG_ERR, "Error in connection setup") | |||
| ; | ||||
| } | ||||
| qb_ipcs_disconnect(c); | qb_ipcs_disconnect(c); | |||
| } else if (res != 0) { | ||||
| qb_ipcc_us_sock_close(sock); | ||||
| } | } | |||
| return res; | return res; | |||
| } | } | |||
| static void handle_connection_new_sock(struct qb_ipcs_service *s, | static void | |||
| int32_t sock, void *msg) | handle_connection_new_sock(struct qb_ipcs_service *s, int32_t sock, void *m | |||
| sg) | ||||
| { | { | |||
| struct qb_ipcs_connection *c = NULL; | struct qb_ipcs_connection *c = NULL; | |||
| struct qb_ipc_event_connection_request *req = msg; | struct qb_ipc_event_connection_request *req = msg; | |||
| c = (struct qb_ipcs_connection *)req->connection; | c = (struct qb_ipcs_connection *)req->connection; | |||
| c->event.u.us.sock = sock; | c->event.u.us.sock = sock; | |||
| } | } | |||
| static int32_t qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len | static int32_t | |||
| , | qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len, | |||
| struct ipc_auth_ugp *ugp) | struct ipc_auth_ugp *ugp) | |||
| { | { | |||
| int32_t res = 0; | int32_t res = 0; | |||
| struct msghdr msg_recv; | struct msghdr msg_recv; | |||
| struct iovec iov_recv; | struct iovec iov_recv; | |||
| #ifdef QB_LINUX | #ifdef QB_LINUX | |||
| struct cmsghdr *cmsg; | ||||
| char cmsg_cred[CMSG_SPACE(sizeof(struct ucred))]; | char cmsg_cred[CMSG_SPACE(sizeof(struct ucred))]; | |||
| int off = 0; | int off = 0; | |||
| int on = 1; | int on = 1; | |||
| struct ucred *cred; | ||||
| #endif | #endif | |||
| msg_recv.msg_flags = 0; | msg_recv.msg_flags = 0; | |||
| msg_recv.msg_iov = &iov_recv; | msg_recv.msg_iov = &iov_recv; | |||
| msg_recv.msg_iovlen = 1; | msg_recv.msg_iovlen = 1; | |||
| msg_recv.msg_name = 0; | msg_recv.msg_name = 0; | |||
| msg_recv.msg_namelen = 0; | msg_recv.msg_namelen = 0; | |||
| #ifdef QB_LINUX | #ifdef QB_LINUX | |||
| msg_recv.msg_control = (void *)cmsg_cred; | msg_recv.msg_control = (void *)cmsg_cred; | |||
| msg_recv.msg_controllen = sizeof(cmsg_cred); | msg_recv.msg_controllen = sizeof(cmsg_cred); | |||
| #endif | #endif | |||
| skipping to change at line 710 | skipping to change at line 724 | |||
| res = 0; | res = 0; | |||
| } else { | } else { | |||
| res = -errno; | res = -errno; | |||
| } | } | |||
| } | } | |||
| #elif SO_PASSCRED | #elif SO_PASSCRED | |||
| /* | /* | |||
| * Usually Linux systems | * Usually Linux systems | |||
| */ | */ | |||
| cmsg = CMSG_FIRSTHDR(&msg_recv); | { | |||
| assert(cmsg != NULL); | struct ucred cred; | |||
| cred = (struct ucred *)CMSG_DATA(cmsg); | struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg_recv); | |||
| if (cred) { | assert(cmsg != NULL); | |||
| res = 0; | if (CMSG_DATA(cmsg)) { | |||
| ugp->pid = cred->pid; | memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred)) | |||
| ugp->uid = cred->uid; | ; | |||
| ugp->gid = cred->gid; | res = 0; | |||
| } else { | ugp->pid = cred.pid; | |||
| res = -EBADMSG; | ugp->uid = cred.uid; | |||
| ugp->gid = cred.gid; | ||||
| } else { | ||||
| res = -EBADMSG; | ||||
| } | ||||
| } | } | |||
| #else /* no credentials */ | #else /* no credentials */ | |||
| ugp->pid = 0; | ugp->pid = 0; | |||
| ugp->uid = 0; | ugp->uid = 0; | |||
| ugp->gid = 0; | ugp->gid = 0; | |||
| res = -ENOTSUP; | res = -ENOTSUP; | |||
| #endif /* no credentials */ | #endif /* no credentials */ | |||
| cleanup_and_return: | cleanup_and_return: | |||
| #ifdef QB_LINUX | #ifdef QB_LINUX | |||
| setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off)); | setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off)); | |||
| #endif | #endif | |||
| return res; | return res; | |||
| } | } | |||
| static int32_t qb_ipcs_us_connection_acceptor(int fd, int revent, void *dat | static int32_t | |||
| a) | qb_ipcs_us_connection_acceptor(int fd, int revent, void *data) | |||
| { | { | |||
| struct sockaddr_un un_addr; | struct sockaddr_un un_addr; | |||
| int32_t new_fd; | int32_t new_fd; | |||
| struct qb_ipcs_service *s = (struct qb_ipcs_service *)data; | struct qb_ipcs_service *s = (struct qb_ipcs_service *)data; | |||
| int32_t res; | int32_t res; | |||
| struct qb_ipc_connection_request setup_msg; | struct qb_ipc_connection_request setup_msg; | |||
| struct ipc_auth_ugp ugp; | struct ipc_auth_ugp ugp; | |||
| socklen_t addrlen = sizeof(struct sockaddr_un); | socklen_t addrlen = sizeof(struct sockaddr_un); | |||
| char error_str[100]; | ||||
| retry_accept: | retry_accept: | |||
| errno = 0; | errno = 0; | |||
| new_fd = accept(fd, (struct sockaddr *)&un_addr, &addrlen); | new_fd = accept(fd, (struct sockaddr *)&un_addr, &addrlen); | |||
| if (new_fd == -1 && errno == EINTR) { | if (new_fd == -1 && errno == EINTR) { | |||
| goto retry_accept; | goto retry_accept; | |||
| } | } | |||
| if (new_fd == -1 && errno == EBADF) { | if (new_fd == -1 && errno == EBADF) { | |||
| strerror_r(errno, error_str, 100); | qb_util_perror(LOG_ERR, | |||
| qb_util_log(LOG_ERR, | "Could not accept client connection from fd:% | |||
| "Could not accept Library connection:(fd: %d) [% | d", | |||
| d] %s", | fd); | |||
| fd, errno, error_str); | ||||
| return -1; | return -1; | |||
| } | } | |||
| if (new_fd == -1) { | if (new_fd == -1) { | |||
| res = -errno; | res = -errno; | |||
| qb_util_log(LOG_ERR, | qb_util_perror(LOG_ERR, "Could not accept client connection" | |||
| "Could not accept Library connection: [%d] %s", | ); | |||
| errno, strerror(-res)); | /* This is an error, but -1 would indicate disconnect | |||
| return 0; /* This is an error, but -1 would indicate d | * from the poll loop | |||
| isconnect from poll loop */ | */ | |||
| return 0; | ||||
| } | } | |||
| res = qb_util_fd_nonblock_cloexec_set(new_fd); | res = qb_sys_fd_nonblock_cloexec_set(new_fd); | |||
| if (res < 0) { | if (res < 0) { | |||
| close(new_fd); | close(new_fd); | |||
| return 0; /* This is an error, but -1 would indicate d | /* This is an error, but -1 would indicate disconnect | |||
| isconnect from poll loop */ | * from the poll loop | |||
| */ | ||||
| return 0; | ||||
| } | } | |||
| res = qb_ipcs_uc_recv_and_auth(new_fd, &setup_msg, sizeof(setup_msg) , | res = qb_ipcs_uc_recv_and_auth(new_fd, &setup_msg, sizeof(setup_msg) , | |||
| &ugp); | &ugp); | |||
| if (setup_msg.hdr.id == QB_IPC_MSG_AUTHENTICATE) { | if (setup_msg.hdr.id == QB_IPC_MSG_AUTHENTICATE) { | |||
| res = handle_new_connection(s, res, new_fd, &setup_msg, size | res = handle_new_connection(s, res, new_fd, &setup_msg, | |||
| of(setup_msg), | sizeof(setup_msg), &ugp); | |||
| &ugp); | ||||
| } else if (setup_msg.hdr.id == QB_IPC_MSG_NEW_EVENT_SOCK) { | } else if (setup_msg.hdr.id == QB_IPC_MSG_NEW_EVENT_SOCK) { | |||
| if (res == 0) { | if (res == 0) { | |||
| handle_connection_new_sock(s, new_fd, &setup_msg); | handle_connection_new_sock(s, new_fd, &setup_msg); | |||
| } else { | } else { | |||
| close(new_fd); | close(new_fd); | |||
| } | } | |||
| } else { | } else { | |||
| close(new_fd); | close(new_fd); | |||
| } | } | |||
| return 0; | return 0; | |||
| } | } | |||
| static int32_t qb_ipcs_us_connect(struct qb_ipcs_service *s, | static int32_t | |||
| struct qb_ipcs_connection *c, | qb_ipcs_us_connect(struct qb_ipcs_service *s, | |||
| struct qb_ipc_connection_response *r) | struct qb_ipcs_connection *c, | |||
| struct qb_ipc_connection_response *r) | ||||
| { | { | |||
| char path[PATH_MAX]; | char path[PATH_MAX]; | |||
| int32_t fd_hdr; | int32_t fd_hdr; | |||
| int32_t res = 0; | int32_t res = 0; | |||
| struct ipc_us_control * ctl; | struct ipc_us_control *ctl; | |||
| qb_util_log(LOG_DEBUG, "connecting to client [%d]", c->pid); | qb_util_log(LOG_DEBUG, "connecting to client [%d]", c->pid); | |||
| snprintf(r->request, NAME_MAX, "qb-%s-control-%d-%d", | snprintf(r->request, NAME_MAX, "qb-%s-control-%d-%d", | |||
| s->name, c->pid, c->setup.u.us.sock); | s->name, c->pid, c->setup.u.us.sock); | |||
| fd_hdr = qb_util_mmap_file_open(path, r->request, | fd_hdr = qb_sys_mmap_file_open(path, r->request, | |||
| sizeof(struct ipc_us_control), | sizeof(struct ipc_us_control), | |||
| O_CREAT | O_TRUNC | O_RDWR); | O_CREAT | O_TRUNC | O_RDWR); | |||
| if (fd_hdr < 0) { | if (fd_hdr < 0) { | |||
| res = -errno; | res = -errno; | |||
| qb_util_log(LOG_ERR, "couldn't create file for mmap: %s", | qb_util_perror(LOG_ERR, "couldn't create file for mmap"); | |||
| strerror(-res)); | ||||
| return res; | return res; | |||
| } | } | |||
| strcpy(r->request, path); | strcpy(r->request, path); | |||
| strcpy(c->request.u.us.shared_file_name, r->request); | strcpy(c->request.u.us.shared_file_name, r->request); | |||
| c->request.u.us.shared_data = mmap(0, | c->request.u.us.shared_data = mmap(0, | |||
| sizeof(struct ipc_us_control), | sizeof(struct ipc_us_control), | |||
| PROT_READ | PROT_WRITE, MAP_SHARE D, | PROT_READ | PROT_WRITE, MAP_SHARE D, | |||
| fd_hdr, 0); | fd_hdr, 0); | |||
| if (c->request.u.us.shared_data == MAP_FAILED) { | if (c->request.u.us.shared_data == MAP_FAILED) { | |||
| res = -errno; | res = -errno; | |||
| qb_util_log(LOG_ERR, "couldn't create mmap for header"); | qb_util_perror(LOG_ERR, "couldn't create mmap for header"); | |||
| goto cleanup_hdr; | goto cleanup_hdr; | |||
| } | } | |||
| ctl = (struct ipc_us_control *)c->request.u.us.shared_data; | ctl = (struct ipc_us_control *)c->request.u.us.shared_data; | |||
| ctl->sent = 0; | ctl->sent = 0; | |||
| ctl->flow_control = 0; | ctl->flow_control = 0; | |||
| close(fd_hdr); | close(fd_hdr); | |||
| return res; | return res; | |||
| cleanup_hdr: | cleanup_hdr: | |||
| close(fd_hdr); | close(fd_hdr); | |||
| unlink(r->request); | unlink(r->request); | |||
| munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control)); | munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control)); | |||
| return res; | return res; | |||
| } | } | |||
| static void qb_ipc_us_fc_set(struct qb_ipc_one_way *one_way, | static void | |||
| int32_t fc_enable) | qb_ipc_us_fc_set(struct qb_ipc_one_way *one_way, int32_t fc_enable) | |||
| { | { | |||
| struct ipc_us_control *ctl = (struct ipc_us_control *)one_way->u.us. | struct ipc_us_control *ctl = | |||
| shared_data; | (struct ipc_us_control *)one_way->u.us.shared_data; | |||
| qb_util_log(LOG_TRACE, "setting fc to %d", fc_enable); | ||||
| qb_atomic_int_set(&ctl->flow_control, fc_enable); | qb_atomic_int_set(&ctl->flow_control, fc_enable); | |||
| } | } | |||
| static int32_t qb_ipc_us_fc_get(struct qb_ipc_one_way *one_way) | static int32_t | |||
| qb_ipc_us_fc_get(struct qb_ipc_one_way *one_way) | ||||
| { | { | |||
| struct ipc_us_control *ctl = (struct ipc_us_control *)one_way->u.us. | struct ipc_us_control *ctl = | |||
| shared_data; | (struct ipc_us_control *)one_way->u.us.shared_data; | |||
| return qb_atomic_int_get(&ctl->flow_control); | return qb_atomic_int_get(&ctl->flow_control); | |||
| } | } | |||
| static ssize_t qb_ipc_us_q_len_get(struct qb_ipc_one_way *one_way) | static ssize_t | |||
| qb_ipc_us_q_len_get(struct qb_ipc_one_way *one_way) | ||||
| { | { | |||
| struct ipc_us_control *ctl = (struct ipc_us_control *)one_way->u.us. | struct ipc_us_control *ctl = | |||
| shared_data; | (struct ipc_us_control *)one_way->u.us.shared_data; | |||
| return qb_atomic_int_get(&ctl->sent); | return qb_atomic_int_get(&ctl->sent); | |||
| } | } | |||
| static void qb_ipcs_us_disconnect(struct qb_ipcs_connection *c) | static void | |||
| qb_ipcs_us_disconnect(struct qb_ipcs_connection *c) | ||||
| { | { | |||
| munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control)); | munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control)); | |||
| unlink(c->request.u.us.shared_file_name); | unlink(c->request.u.us.shared_file_name); | |||
| // close(c->setup.u.us.sock); | ||||
| close(c->request.u.us.sock); | close(c->request.u.us.sock); | |||
| // close(c->response.u.us.sock); | ||||
| close(c->event.u.us.sock); | close(c->event.u.us.sock); | |||
| } | } | |||
| void qb_ipcs_us_init(struct qb_ipcs_service *s) | void | |||
| qb_ipcs_us_init(struct qb_ipcs_service *s) | ||||
| { | { | |||
| s->funcs.connect = qb_ipcs_us_connect; | s->funcs.connect = qb_ipcs_us_connect; | |||
| s->funcs.disconnect = qb_ipcs_us_disconnect; | s->funcs.disconnect = qb_ipcs_us_disconnect; | |||
| s->funcs.recv = qb_ipc_us_recv; | s->funcs.recv = qb_ipc_us_recv; | |||
| s->funcs.peek = NULL; | s->funcs.peek = NULL; | |||
| s->funcs.reclaim = NULL; | s->funcs.reclaim = NULL; | |||
| s->funcs.send = qb_ipc_us_send; | s->funcs.send = qb_ipc_us_send; | |||
| s->funcs.sendv = qb_ipc_us_sendv; | s->funcs.sendv = qb_ipc_us_sendv; | |||
| End of changes. 84 change blocks. | ||||
| 160 lines changed or deleted | 173 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||