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.
- Assign the size of option value to socklen_t optlen before passing
  into the setsockopt and getsockopt options to avoid inconsistent
  error due to int to socklen_t conversion.

Issue: eclipse-omr#5158

Signed-off-by: Haley Cao <haleycao88@hotmail.com>
  • Loading branch information
Haley Cao committed Jun 15, 2020
1 parent 5201aea commit 335c79a
Show file tree
Hide file tree
Showing 2 changed files with 149 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
151 changes: 145 additions & 6 deletions port/unix/omrsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,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] OMRSocketLevel 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 OMRSocketLevel)
{
switch (OMRSocketLevel)
{
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] OMRSocketOption 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 OMRSocketOption)
{
switch (OMRSocketOption)
{
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 @@ -683,40 +749,113 @@ 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;
socklen_t optlen = sizeof(int32_t);
return set_opt(portLibrary, handle->data, optlevel, optname, (void*)optval, optlen);
}

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;
socklen_t optlen = sizeof(struct linger);
return set_opt(portLibrary, handle->data, optlevel, optname, (void*)&optval->data, optlen);
}

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;
socklen_t optlen = sizeof(struct timeval);
return set_opt(portLibrary, handle->data, optlevel, optname, (void*)&optval->data, optlen);
}

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;
socklen_t optlen = sizeof(int32_t);
return get_opt(portLibrary, handle->data, optlevel, optname, (void*)optval, optlen);
}

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;
socklen_t optlen = sizeof(struct linger);
return get_opt(portLibrary, handle->data, optlevel, optname, (void*)&optval->data, optlen);
}

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;
socklen_t optlen = sizeof(struct timeval);
return get_opt(portLibrary, handle->data, optlevel, optname, (void*)&optval->data, optlen);
}

#endif /* defined(OMR_PORT_SOCKET_SUPPORT) */

0 comments on commit 335c79a

Please sign in to comment.