ipcc.c | ipcc.c | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* 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" | |||
#ifdef HAVE_MQUEUE_H | ||||
#include <mqueue.h> | #include <mqueue.h> | |||
#endif /* HAVE_MQUEUE_H */ | ||||
#include "ipc_int.h" | #include "ipc_int.h" | |||
#include "util_int.h" | #include "util_int.h" | |||
#include <qb/qbdefs.h> | #include <qb/qbdefs.h> | |||
#include <qb/qbipcc.h> | #include <qb/qbipcc.h> | |||
qb_ipcc_connection_t *qb_ipcc_connect(const char *name, size_t max_msg_size | qb_ipcc_connection_t * | |||
) | qb_ipcc_connect(const char *name, size_t max_msg_size) | |||
{ | { | |||
int32_t res; | int32_t res; | |||
qb_ipcc_connection_t *c = NULL; | qb_ipcc_connection_t *c = NULL; | |||
struct qb_ipc_connection_response response; | struct qb_ipc_connection_response response; | |||
c = calloc(1, sizeof(struct qb_ipcc_connection)); | c = calloc(1, sizeof(struct qb_ipcc_connection)); | |||
if (c == NULL) { | if (c == NULL) { | |||
return NULL; | return NULL; | |||
} | } | |||
skipping to change at line 51 | skipping to change at line 54 | |||
strcpy(c->name, name); | strcpy(c->name, name); | |||
res = qb_ipcc_us_setup_connect(c, &response); | res = qb_ipcc_us_setup_connect(c, &response); | |||
if (res < 0) { | if (res < 0) { | |||
goto disconnect_and_cleanup; | goto disconnect_and_cleanup; | |||
} | } | |||
c->type = response.connection_type; | c->type = response.connection_type; | |||
c->response.max_msg_size = response.max_msg_size; | c->response.max_msg_size = response.max_msg_size; | |||
c->request.max_msg_size = response.max_msg_size; | c->request.max_msg_size = response.max_msg_size; | |||
c->event.max_msg_size = response.max_msg_size; | c->event.max_msg_size = response.max_msg_size; | |||
c->receive_buf = malloc(response.max_msg_size); | c->receive_buf = malloc(response.max_msg_size); | |||
c->fc_enable_max = 1; | ||||
if (c->receive_buf == NULL) { | ||||
res = -ENOMEM; | ||||
goto disconnect_and_cleanup; | ||||
} | ||||
switch (c->type) { | switch (c->type) { | |||
case QB_IPC_SHM: | case QB_IPC_SHM: | |||
res = qb_ipcc_shm_connect(c, &response); | res = qb_ipcc_shm_connect(c, &response); | |||
break; | break; | |||
case QB_IPC_POSIX_MQ: | case QB_IPC_POSIX_MQ: | |||
#ifdef HAVE_POSIX_MQ | ||||
res = qb_ipcc_pmq_connect(c, &response); | res = qb_ipcc_pmq_connect(c, &response); | |||
#else | ||||
res = -ENOTSUP; | ||||
#endif /* HAVE_POSIX_MQ */ | ||||
break; | break; | |||
case QB_IPC_SYSV_MQ: | case QB_IPC_SYSV_MQ: | |||
#ifdef HAVE_SYSV_MQ | ||||
res = qb_ipcc_smq_connect(c, &response); | res = qb_ipcc_smq_connect(c, &response); | |||
#else | ||||
res = -ENOTSUP; | ||||
#endif /* HAVE_SYSV_MQ */ | ||||
break; | break; | |||
case QB_IPC_SOCKET: | case QB_IPC_SOCKET: | |||
res = qb_ipcc_us_connect(c, &response); | res = qb_ipcc_us_connect(c, &response); | |||
break; | break; | |||
default: | default: | |||
res = -EINVAL; | res = -EINVAL; | |||
break; | break; | |||
} | } | |||
if (res != 0) { | if (res != 0) { | |||
goto disconnect_and_cleanup; | goto disconnect_and_cleanup; | |||
} | } | |||
return c; | return c; | |||
disconnect_and_cleanup: | disconnect_and_cleanup: | |||
qb_ipcc_us_sock_close(c->setup.u.us.sock); | qb_ipcc_us_sock_close(c->setup.u.us.sock); | |||
free(c->receive_buf); | ||||
free(c); | free(c); | |||
errno = -res; | errno = -res; | |||
return NULL; | return NULL; | |||
} | } | |||
ssize_t qb_ipcc_send(struct qb_ipcc_connection * c, const void *msg_ptr, | ssize_t | |||
size_t msg_len) | qb_ipcc_send(struct qb_ipcc_connection * c, const void *msg_ptr, size_t msg | |||
_len) | ||||
{ | { | |||
ssize_t res; | ssize_t res; | |||
ssize_t res2; | ssize_t res2; | |||
if (msg_len > c->request.max_msg_size) { | if (c == NULL || msg_len > c->request.max_msg_size) { | |||
return -EINVAL; | return -EINVAL; | |||
} | } | |||
if (c->funcs.fc_get) { | if (c->funcs.fc_get) { | |||
res = c->funcs.fc_get(&c->request); | res = c->funcs.fc_get(&c->request); | |||
if (res < 0) { | if (res < 0) { | |||
return res; | return res; | |||
} else if (res > 0) { | } else if (res > 0 && res <= c->fc_enable_max) { | |||
return -EAGAIN; | return -EAGAIN; | |||
} else { | } else { | |||
/* | /* | |||
* we can transmit | * we can transmit | |||
*/ | */ | |||
} | } | |||
} | } | |||
res = c->funcs.send(&c->request, msg_ptr, msg_len); | res = c->funcs.send(&c->request, msg_ptr, msg_len); | |||
if (res == msg_len && c->needs_sock_for_poll) { | if (res == msg_len && c->needs_sock_for_poll) { | |||
skipping to change at line 118 | skipping to change at line 135 | |||
if (res2 == -EPIPE) { | if (res2 == -EPIPE) { | |||
return -ENOTCONN; | return -ENOTCONN; | |||
} | } | |||
if (res2 != 1) { | if (res2 != 1) { | |||
res = res2; | res = res2; | |||
} | } | |||
} | } | |||
return res; | return res; | |||
} | } | |||
ssize_t qb_ipcc_sendv(struct qb_ipcc_connection* c, const struct iovec* iov | int32_t | |||
, | qb_ipcc_fc_enable_max_set(struct qb_ipcc_connection * c, uint32_t max) | |||
size_t iov_len) | { | |||
if (c == NULL || max > 2) { | ||||
return -EINVAL; | ||||
} | ||||
c->fc_enable_max = max; | ||||
return 0; | ||||
} | ||||
ssize_t | ||||
qb_ipcc_sendv(struct qb_ipcc_connection * c, const struct iovec * iov, | ||||
size_t iov_len) | ||||
{ | { | |||
int32_t total_size = 0; | int32_t total_size = 0; | |||
int32_t i; | int32_t i; | |||
int32_t res; | int32_t res; | |||
int32_t res2; | int32_t res2; | |||
for (i = 0; i < iov_len; i++) { | for (i = 0; i < iov_len; i++) { | |||
total_size += iov[i].iov_len; | total_size += iov[i].iov_len; | |||
} | } | |||
if (total_size > c->request.max_msg_size) { | if (c == NULL || total_size > c->request.max_msg_size) { | |||
return -EINVAL; | return -EINVAL; | |||
} | } | |||
if (c->funcs.fc_get) { | if (c->funcs.fc_get) { | |||
res = c->funcs.fc_get(&c->request); | res = c->funcs.fc_get(&c->request); | |||
if (res < 0) { | if (res < 0) { | |||
return res; | return res; | |||
} else if (res > 0) { | } else if (res > 0 && res <= c->fc_enable_max) { | |||
return -EAGAIN; | return -EAGAIN; | |||
} else { | } else { | |||
/* | /* | |||
* we can transmit | * we can transmit | |||
*/ | */ | |||
} | } | |||
} | } | |||
res = c->funcs.sendv(&c->request, iov, iov_len); | res = c->funcs.sendv(&c->request, iov, iov_len); | |||
if (res > 0 && c->needs_sock_for_poll) { | if (res > 0 && c->needs_sock_for_poll) { | |||
skipping to change at line 161 | skipping to change at line 189 | |||
if (res2 == -EPIPE) { | if (res2 == -EPIPE) { | |||
return -ENOTCONN; | return -ENOTCONN; | |||
} | } | |||
if (res2 != 1) { | if (res2 != 1) { | |||
res = res2; | res = res2; | |||
} | } | |||
} | } | |||
return res; | return res; | |||
} | } | |||
ssize_t qb_ipcc_recv(struct qb_ipcc_connection * c, void *msg_ptr, | ssize_t | |||
size_t msg_len, int32_t ms_timeout) | qb_ipcc_recv(struct qb_ipcc_connection * c, void *msg_ptr, | |||
size_t msg_len, int32_t ms_timeout) | ||||
{ | { | |||
int32_t res = 0; | int32_t res = 0; | |||
int32_t res2 = 0; | int32_t res2 = 0; | |||
if (c == NULL) { | ||||
return -EINVAL; | ||||
} | ||||
res = c->funcs.recv(&c->response, msg_ptr, msg_len, ms_timeout); | res = c->funcs.recv(&c->response, msg_ptr, msg_len, ms_timeout); | |||
if ((res == -EAGAIN || res == -ETIMEDOUT) && c->needs_sock_for_poll) { | if ((res == -EAGAIN || res == -ETIMEDOUT) && c->needs_sock_for_poll) { | |||
res2 = qb_ipc_us_recv_ready(&c->setup, 0); | res2 = qb_ipc_us_recv_ready(&c->setup, 0); | |||
if (res2 < 0) { | if (res2 < 0) { | |||
return res2; | return res2; | |||
} else { | } else { | |||
return res; | return res; | |||
} | } | |||
} | } | |||
return res; | return res; | |||
} | } | |||
ssize_t qb_ipcc_sendv_recv(qb_ipcc_connection_t *c, | ssize_t | |||
const struct iovec *iov, uint32_t iov_len, | qb_ipcc_sendv_recv(qb_ipcc_connection_t * c, | |||
void *res_msg, size_t res_len, | const struct iovec * iov, uint32_t iov_len, | |||
int32_t ms_timeout) | void *res_msg, size_t res_len, int32_t ms_timeout) | |||
{ | { | |||
ssize_t res = 0; | ssize_t res = 0; | |||
if (c == NULL) { | ||||
return -EINVAL; | ||||
} | ||||
if (c->funcs.fc_get) { | if (c->funcs.fc_get) { | |||
res = c->funcs.fc_get(&c->request); | res = c->funcs.fc_get(&c->request); | |||
if (res < 0) { | if (res < 0) { | |||
return res; | return res; | |||
} else if (res > 0) { | } else if (res > 0 && res <= c->fc_enable_max) { | |||
return -EAGAIN; | return -EAGAIN; | |||
} else { | } else { | |||
/* | /* | |||
* we can transmit | * we can transmit | |||
*/ | */ | |||
} | } | |||
} | } | |||
res = qb_ipcc_sendv(c, iov, iov_len); | res = qb_ipcc_sendv(c, iov, iov_len); | |||
if (res < 0) { | if (res < 0) { | |||
return res; | return res; | |||
} | } | |||
return qb_ipcc_recv(c, res_msg, res_len, ms_timeout); | return qb_ipcc_recv(c, res_msg, res_len, ms_timeout); | |||
} | } | |||
int32_t qb_ipcc_fd_get(struct qb_ipcc_connection * c, int32_t * fd) | int32_t | |||
qb_ipcc_fd_get(struct qb_ipcc_connection * c, int32_t * fd) | ||||
{ | { | |||
if (c == NULL) { | ||||
return -EINVAL; | ||||
} | ||||
if (c->type == QB_IPC_SOCKET) { | if (c->type == QB_IPC_SOCKET) { | |||
*fd = c->event.u.us.sock; | *fd = c->event.u.us.sock; | |||
} else { | } else { | |||
*fd = c->setup.u.us.sock; | *fd = c->setup.u.us.sock; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
ssize_t qb_ipcc_event_recv(struct qb_ipcc_connection * c, void *msg_pt, | ssize_t | |||
size_t msg_len, int32_t ms_timeout) | qb_ipcc_event_recv(struct qb_ipcc_connection * c, void *msg_pt, | |||
size_t msg_len, int32_t ms_timeout) | ||||
{ | { | |||
char one_byte = 1; | char one_byte = 1; | |||
int32_t res; | int32_t res; | |||
ssize_t size; | ssize_t size; | |||
struct qb_ipc_one_way *ow = NULL; | struct qb_ipc_one_way *ow = NULL; | |||
if (c == NULL) { | ||||
return -EINVAL; | ||||
} | ||||
if (c->needs_sock_for_poll) { | if (c->needs_sock_for_poll) { | |||
ow = &c->setup; | ow = &c->setup; | |||
} | } | |||
if (c->type == QB_IPC_SOCKET) { | if (c->type == QB_IPC_SOCKET) { | |||
ow = &c->event; | ow = &c->event; | |||
} | } | |||
if (ow) { | if (ow) { | |||
res = qb_ipc_us_recv_ready(ow, ms_timeout); | res = qb_ipc_us_recv_ready(ow, ms_timeout); | |||
if (res < 0) { | if (res < 0) { | |||
return res; | return res; | |||
skipping to change at line 250 | skipping to change at line 294 | |||
} | } | |||
if (c->needs_sock_for_poll) { | if (c->needs_sock_for_poll) { | |||
res = qb_ipc_us_recv(&c->setup, &one_byte, 1, -1); | res = qb_ipc_us_recv(&c->setup, &one_byte, 1, -1); | |||
if (res < 0) { | if (res < 0) { | |||
return res; | return res; | |||
} | } | |||
} | } | |||
return size; | return size; | |||
} | } | |||
void qb_ipcc_disconnect(struct qb_ipcc_connection *c) | void | |||
qb_ipcc_disconnect(struct qb_ipcc_connection *c) | ||||
{ | { | |||
qb_util_log(LOG_DEBUG, "%s()", __func__); | qb_util_log(LOG_DEBUG, "%s()", __func__); | |||
if (c == NULL) { | ||||
return; | ||||
} | ||||
qb_ipcc_us_sock_close(c->setup.u.us.sock); | qb_ipcc_us_sock_close(c->setup.u.us.sock); | |||
if (c->funcs.disconnect) { | if (c->funcs.disconnect) { | |||
c->funcs.disconnect(c); | c->funcs.disconnect(c); | |||
} | } | |||
free(c->receive_buf); | free(c->receive_buf); | |||
free(c); | free(c); | |||
} | } | |||
End of changes. 27 change blocks. | ||||
23 lines changed or deleted | 70 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/ |