Skip to content

Commit

Permalink
Added Unix Implementations for Socket Opt Functions
Browse files Browse the repository at this point in the history
Added internal functions and implementations for sockopt functions

- Added 4 internal functions: one to retrieve OMR to OS mapping
  for socket levels, one to retrieve OMR to OS mapping for socket
  options, two to wrap the code for the socket option functions
  to reduce clutter.
- Added simple implemnentations for the 6 socket options functions.

Issue: eclipse-omr#5158

Signed-off-by: Haley Cao <haleycao88@hotmail.com>
  • Loading branch information
Haley Cao committed Jun 24, 2020
1 parent f897939 commit 1eea53f
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 6 deletions.
4 changes: 4 additions & 0 deletions include_core/omrporterror.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@
#define OMRPORT_ERROR_SOCK_ACCEPT_FAILED (OMRPORT_ERROR_SOCK_BASE - 10)
#define OMRPORT_ERROR_SOCK_SEND_FAILED (OMRPORT_ERROR_SOCK_BASE - 11)
#define OMRPORT_ERROR_SOCK_RECV_FAILED (OMRPORT_ERROR_SOCK_BASE - 12)
#define OMRPORT_ERROR_SOCK_LEVEL_UNSUPPORTED (OMRPORT_ERROR_SOCK_BASE - 13)
#define OMRPORT_ERROR_SOCK_OPTION_UNSUPPORTED (OMRPORT_ERROR_SOCK_BASE - 14)
#define OMRPORT_ERROR_SOCK_SETSOCKOPT_FAILED (OMRPORT_ERROR_SOCK_BASE - 15)
#define OMRPORT_ERROR_SOCK_GETSOCKOPT_FAILED (OMRPORT_ERROR_SOCK_BASE - 16)
/**
* @}
*/
Expand Down
148 changes: 142 additions & 6 deletions port/unix/omrsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,72 @@ get_omr_protocol(int32_t osProtocol)
return OMRSOCK_IPPROTO_DEFAULT;
}

/**
* @internal Map OMRSOCK API user interface socket level to
* OS socket level. Used to resolve the arguments of socket
* option functions.
*
* Socket Levels currently supported are:
* \arg OMRSOCK_SOL_SOCKET, for most options.
* \arg OMRSOCK_IPPROTO_TCP, for the TCP noDelay option.
*
* @param[in] socketLevel The OMR socket level to be converted.
*
* @return OS protocol on success, or OS_SOL_SOCKET if none exists.
*/
static int32_t
get_os_socket_level(int32_t socketLevel)
{
switch (socketLevel)
{
case OMRSOCK_SOL_SOCKET:
return OS_SOL_SOCKET;
case OMRSOCK_IPPROTO_TCP:
return OS_SOCK_IPPROTO_TCP;
default:
break;
}
return OMRPORT_ERROR_SOCK_LEVEL_UNSUPPORTED;
}

/**
* @internal Map OMRSOCK API user interface socket option to OS socket option.
* Used to resolve the arguments of socket option functions.
* Options currently in supported are:
* \arg SO_KEEPALIVE, the keep-alive messages are enabled.
* \arg SO_LINGER, the linger timeout.
* \arg SO_REUSEADDR, the reusage of local address are allowed in bind.
* \arg SO_RCVTIMEO, the receive timeout.
* \arg SO_SNDTIMEO, the send timeout.
* \arg TCP_NODELAY, the buffering scheme disabling Nagle's algorithm.
*
* @param[in] socketOption The portable socket option to convert.
*
* @return OS Socket Option on success, or OS_SOL_SOCKET if none exists.
*/
static int32_t
get_os_socket_option(int32_t socketOption)
{
switch (socketOption)
{
case OMRSOCK_SO_KEEPALIVE:
return OS_SO_KEEPALIVE;
case OMRSOCK_SO_LINGER:
return OS_SO_LINGER;
case OMRSOCK_SO_REUSEADDR:
return OS_SO_REUSEADDR;
case OMRSOCK_SO_RCVTIMEO:
return OS_SO_RCVTIMEO;
case OMRSOCK_SO_SNDTIMEO:
return OS_SO_SNDTIMEO;
case OMRSOCK_TCP_NODELAY:
return OS_TCP_NODELAY;
default:
break;
}
return OMRPORT_ERROR_SOCK_OPTION_UNSUPPORTED;
}

int32_t
omrsock_startup(struct OMRPortLibrary *portLibrary)
{
Expand Down Expand Up @@ -680,38 +746,108 @@ omrsock_linger_init(struct OMRPortLibrary *portLibrary, omrsock_linger_t handle,
return 0;
}

/**
* @internal Set socket options for all option value types, since pointers to option values are casted to void types.
*
* @param portLibrary The port library.
* @param sock Pointer to the socket to set the option in.
* @param optlevel The level within the IP stack at which the option is defined.
* @param optname The name of the option to set.
* @param optval Void type pointer to the option value to update the socket option with.
* @param len Length of the option value.
*
* @return 0, if no errors occurred, otherwise return an error.
*/
int32_t
set_opt(struct OMRPortLibrary *portLibrary, omr_os_socket sock, int32_t optlevel, int32_t optname, void *optval, socklen_t len)
{
int32_t osLevel = get_os_socket_level(optlevel);
int32_t osOption = get_os_socket_option(optname);

if (osLevel == OMRPORT_ERROR_SOCK_LEVEL_UNSUPPORTED) {
return OMRPORT_ERROR_SOCK_LEVEL_UNSUPPORTED;
}

if (osOption == OMRPORT_ERROR_SOCK_OPTION_UNSUPPORTED) {
return OMRPORT_ERROR_SOCK_OPTION_UNSUPPORTED;
}

if (0 != setsockopt(sock, osLevel, osOption, optval, len)) {
portLibrary->error_set_last_error(portLibrary, errno, OMRPORT_ERROR_SOCK_SETSOCKOPT_FAILED);
return OMRPORT_ERROR_SOCK_SETSOCKOPT_FAILED;
}

return 0;
}

/**
* @internal Get socket options for all option value types, since pointers to option values are casted to void types.
* Opposite of @ref set_opt.
*
* @param portLibrary The port library.
* @param sock Pointer to the socket to query for the option value.
* @param optlevel The level within the IP stack at which the option is defined.
* @param optname The name of the option to retrieve.
* @param optval Void type pointer to the pre-allocated space to update with the option value.
* @param len Length of the option value.
*
* @return 0, if no errors occurred, otherwise return an error.
*/
int32_t
get_opt(struct OMRPortLibrary *portLibrary, omr_os_socket sock, int32_t optlevel, int32_t optname, void *optval, socklen_t len)
{
int32_t osLevel = get_os_socket_level(optlevel);
int32_t osOption = get_os_socket_option(optname);
socklen_t optlen = len;

if (osLevel == OMRPORT_ERROR_SOCK_LEVEL_UNSUPPORTED) {
return OMRPORT_ERROR_SOCK_LEVEL_UNSUPPORTED;
}

if (osOption == OMRPORT_ERROR_SOCK_OPTION_UNSUPPORTED) {
return OMRPORT_ERROR_SOCK_OPTION_UNSUPPORTED;
}

if (0 != getsockopt(sock, osLevel, osOption, optval, &optlen)) {
portLibrary->error_set_last_error(portLibrary, errno, OMRPORT_ERROR_SOCK_GETSOCKOPT_FAILED);
return OMRPORT_ERROR_SOCK_GETSOCKOPT_FAILED;
}

return 0;
}

int32_t
omrsock_setsockopt_int(struct OMRPortLibrary *portLibrary, omrsock_socket_t handle, int32_t optlevel, int32_t optname, int32_t *optval)
{
return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM;
return set_opt(portLibrary, handle->data, optlevel, optname, (void*)optval, sizeof(int32_t));
}

int32_t
omrsock_setsockopt_linger(struct OMRPortLibrary *portLibrary, omrsock_socket_t handle, int32_t optlevel, int32_t optname, omrsock_linger_t optval)
{
return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM;
return set_opt(portLibrary, handle->data, optlevel, optname, (void*)&optval->data, sizeof(struct linger));
}

int32_t
omrsock_setsockopt_timeval(struct OMRPortLibrary *portLibrary, omrsock_socket_t handle, int32_t optlevel, int32_t optname, omrsock_timeval_t optval)
{
return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM;
return set_opt(portLibrary, handle->data, optlevel, optname, (void*)&optval->data, sizeof(struct timeval));
}

int32_t
omrsock_getsockopt_int(struct OMRPortLibrary *portLibrary, omrsock_socket_t handle, int32_t optlevel, int32_t optname, int32_t *optval)
{
return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM;
return get_opt(portLibrary, handle->data, optlevel, optname, (void*)optval, sizeof(int32_t));
}

int32_t
omrsock_getsockopt_linger(struct OMRPortLibrary *portLibrary, omrsock_socket_t handle, int32_t optlevel, int32_t optname, omrsock_linger_t optval)
{
return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM;
return get_opt(portLibrary, handle->data, optlevel, optname, (void*)&optval->data, sizeof(struct linger));
}

int32_t
omrsock_getsockopt_timeval(struct OMRPortLibrary *portLibrary, omrsock_socket_t handle, int32_t optlevel, int32_t optname, omrsock_timeval_t optval)
{
return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM;
return get_opt(portLibrary, handle->data, optlevel, optname, (void*)&optval->data, sizeof(struct timeval));
}

0 comments on commit 1eea53f

Please sign in to comment.