Skip to content

Commit

Permalink
High: ipcc: Add abilty to verify dgram kernel buffer size meets max m…
Browse files Browse the repository at this point in the history
…sg value
  • Loading branch information
davidvossel committed Jul 19, 2013
1 parent 40e163a commit 65d044b
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
23 changes: 23 additions & 0 deletions include/qb/qbipcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,33 @@ typedef struct qb_ipcc_connection qb_ipcc_connection_t;
* @param name name of the service.
* @param max_msg_size biggest msg size.
* @return NULL (error: see errno) or a connection object.
*
* @note It is recommended to do a one time check on the
* max_msg_size value using qb_ipcc_verify_dgram_max_msg_size
* _BEFORE_ calling the connect function when IPC_SOCKET is in use.
* Some distributions while allow large message buffers to be
* set on the socket, but not actually honor them because of
* kernel state values. The qb_ipcc_verify_dgram_max_msg_size
* function both sets the socket buffer size and verifies it by
* doing a send/recv.
*/
qb_ipcc_connection_t*
qb_ipcc_connect(const char *name, size_t max_msg_size);

/**
* Test kernel dgram socket buffers to verify the largest size up
* to the max_msg_size value a single msg can be. Rounds down to the
* nearest 1k.
*
* @param max_msg_size biggest msg size.
* @return -1 if max size can not be detected, positive value
* representing the largest single msg up to max_msg_size
* that can successfully be sent over a unix dgram socket.
*/
int32_t
qb_ipcc_verify_dgram_max_msg_size(size_t max_msg_size);


/**
* Disconnect an IPC connection.
*
Expand Down
60 changes: 59 additions & 1 deletion lib/ipc_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,72 @@ set_sock_size(int sockfd, size_t max_msg_size)
qb_util_log(LOG_DEBUG, "%d: getsockopt(%d, needed:%d) actual:%d",
rc, sockfd, max_msg_size, optval);

if (rc == 0 && optval < max_msg_size) {
/* the optvat <= max_msg_size check is weird...
* during testing it was discovered in some instances if the
* default optval is exactly equal to our max_msg_size, we couldn't
* actually send a message that large unless we explicilty set
* it using setsockopt... there is no good explaination for this. */
if (rc == 0 && optval <= max_msg_size) {
optval = max_msg_size;
optlen = sizeof(optval);
rc = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &optval, optlen);
}
return rc;
}

static int32_t
dgram_verify_msg_size(size_t max_msg_size)
{
int rc = -1;
int sockets[2];
char buf[max_msg_size];

if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) < 0) {
goto cleanup_socks;
}

if (set_sock_size(sockets[0], max_msg_size) != 0) {
goto cleanup_socks;
}
if (set_sock_size(sockets[1], max_msg_size) != 0) {
goto cleanup_socks;
}

if ((rc = write(sockets[1], buf, max_msg_size)) < 0) {
goto cleanup_socks;
}
if (read(sockets[0], buf, max_msg_size) != max_msg_size) {
goto cleanup_socks;
}

rc = 0;

cleanup_socks:
close(sockets[0]);
close(sockets[1]);
return rc;
}

int32_t
qb_ipcc_verify_dgram_max_msg_size(size_t max_msg_size)
{
int32_t i;
int32_t last = -1;

if (dgram_verify_msg_size(max_msg_size) == 0) {
return max_msg_size;
}

for (i = 1024; i < max_msg_size; i+=1024) {
if (dgram_verify_msg_size(i) != 0) {
break;
}
last = i;
}

return last;
}

/*
* bind to "base_name-local_name"
* connect to "base_name-remote_name"
Expand Down

0 comments on commit 65d044b

Please sign in to comment.