Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1153, add os-specifc socket flag function #1157

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 49 additions & 44 deletions src/os/portable/os-impl-bsd-sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@
DEFINES
****************************************************************************************/

/*
* The OS layer may define a macro to set the proper flags on newly-opened sockets.
* If not set, then a default implementation is used, which uses fcntl() to set O_NONBLOCK
*/
#ifndef OS_IMPL_SOCKET_FLAGS
#ifdef O_NONBLOCK
#define OS_IMPL_SOCKET_FLAGS O_NONBLOCK
#else
#define OS_IMPL_SOCKET_FLAGS 0 /* do not set any flags */
#endif
#endif

#ifndef OS_IMPL_SET_SOCKET_FLAGS
#define OS_IMPL_SET_SOCKET_FLAGS(tok) OS_SetSocketDefaultFlags_Impl(tok)
#endif

typedef union
{
char data[OS_SOCKADDR_MAX_LEN];
Expand All @@ -82,6 +98,37 @@ typedef union
*/
CompileTimeAssert(sizeof(OS_SockAddr_Accessor_t) == OS_SOCKADDR_MAX_LEN, SockAddrSize);

/*
* Default flags implementation: Set the O_NONBLOCK flag via fcntl().
* An implementation can also elect custom configuration by setting
* the OS_IMPL_SET_SOCKET_FLAGS macro to point to an alternate function.
*/
void OS_SetSocketDefaultFlags_Impl(const OS_object_token_t *token)
{
OS_impl_file_internal_record_t *impl;
int os_flags;

impl = OS_OBJECT_TABLE_GET(OS_impl_filehandle_table, *token);

os_flags = fcntl(impl->fd, F_GETFL);
if (os_flags == -1)
{
/* No recourse if F_GETFL fails - just report the error and move on. */
OS_DEBUG("fcntl(F_GETFL): %s\n", strerror(errno));
}
else
{
os_flags |= OS_IMPL_SOCKET_FLAGS;
if (fcntl(impl->fd, F_SETFL, os_flags) == -1)
{
/* No recourse if F_SETFL fails - just report the error and move on. */
OS_DEBUG("fcntl(F_SETFL): %s\n", strerror(errno));
}
}

impl->selectable = true;
}

/****************************************************************************************
Sockets API
***************************************************************************************/
Expand Down Expand Up @@ -160,23 +207,7 @@ int32 OS_SocketOpen_Impl(const OS_object_token_t *token)
* nonblock mode does improve robustness in the event that multiple tasks
* attempt to accept new connections from the same server socket at the same time.
*/
os_flags = fcntl(impl->fd, F_GETFL);
if (os_flags == -1)
{
/* No recourse if F_GETFL fails - just report the error and move on. */
OS_DEBUG("fcntl(F_GETFL): %s\n", strerror(errno));
}
else
{
os_flags |= OS_IMPL_SOCKET_FLAGS;
if (fcntl(impl->fd, F_SETFL, os_flags) == -1)
{
/* No recourse if F_SETFL fails - just report the error and move on. */
OS_DEBUG("fcntl(F_SETFL): %s\n", strerror(errno));
}
}

impl->selectable = OS_IMPL_SOCKET_SELECTABLE;
OS_IMPL_SET_SOCKET_FLAGS(token);

return OS_SUCCESS;
} /* end OS_SocketOpen_Impl */
Expand Down Expand Up @@ -397,7 +428,6 @@ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_
int32 return_code;
uint32 operation;
socklen_t addrlen;
int os_flags;
OS_impl_file_internal_record_t *sock_impl;
OS_impl_file_internal_record_t *conn_impl;

Expand Down Expand Up @@ -432,32 +462,7 @@ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_
{
Addr->ActualLength = addrlen;

/*
* Set the standard options on the filehandle by default --
* this may set it to non-blocking mode if the implementation supports it.
* any blocking would be done explicitly via the select() wrappers
*
* NOTE: The implementation still generally works without this flag set, but
* nonblock mode does improve robustness in the event that multiple tasks
* attempt to read from the same socket at the same time.
*/
os_flags = fcntl(conn_impl->fd, F_GETFL);
if (os_flags == -1)
{
/* No recourse if F_GETFL fails - just report the error and move on. */
OS_DEBUG("fcntl(F_GETFL): %s\n", strerror(errno));
}
else
{
os_flags |= OS_IMPL_SOCKET_FLAGS;
if (fcntl(conn_impl->fd, F_SETFL, os_flags) == -1)
{
/* No recourse if F_SETFL fails - just report the error and move on. */
OS_DEBUG("fcntl(F_SETFL): %s\n", strerror(errno));
}
}

conn_impl->selectable = OS_IMPL_SOCKET_SELECTABLE;
OS_IMPL_SET_SOCKET_FLAGS(conn_token);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/os/shared/inc/os-shared-sockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,5 +188,6 @@ int32 OS_SocketAddrSetPort_Impl(OS_SockAddr_t *Addr, uint16 PortNum);
* Not normally called outside the local unit, except during unit test
*/
void OS_CreateSocketName(const OS_object_token_t *token, const OS_SockAddr_t *Addr, const char *parent_name);
void OS_SetSocketDefaultFlags_Impl(const OS_object_token_t *token);

#endif /* OS_SHARED_SOCKETS_H */
1 change: 1 addition & 0 deletions src/os/vxworks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ if (OSAL_CONFIG_INCLUDE_NETWORK)
list(APPEND VXWORKS_IMPL_SRCLIST
src/os-impl-network.c
../portable/os-impl-bsd-sockets.c # Use BSD socket layer implementation
src/os-impl-sockets.c # Additional vxworks-specific code to handle socket flags
)
else()
list(APPEND VXWORKS_IMPL_SRCLIST
Expand Down
23 changes: 9 additions & 14 deletions src/os/vxworks/inc/os-impl-sockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#define OS_IMPL_SOCKETS_H

#include "os-impl-io.h"
#include "os-shared-globaldefs.h"

#include <fcntl.h>
#include <unistd.h>
Expand All @@ -37,25 +38,19 @@
#include <arpa/inet.h>
#include <netinet/in.h>
#include <hostLib.h>
#include <ioLib.h>

/*
* Socket descriptors should be usable with the select() API
* Override the socket flag set routine on this platform.
* This is required because some versions of VxWorks do not support
* the standard POSIX fcntl() opcodes, and must use ioctl() instead.
*/
#define OS_IMPL_SOCKET_SELECTABLE true

/*
* Use the O_NONBLOCK flag on sockets
*
* NOTE: the fcntl() F_GETFL/F_SETFL opcodes that set descriptor flags may not
* work correctly on some version of VxWorks.
*
* This flag is not strictly required, things still mostly work without it,
* but lack of this mode does introduce some potential race conditions if more
* than one task attempts to use the same descriptor handle at the same time.
*/
#define OS_IMPL_SOCKET_FLAGS O_NONBLOCK
#define OS_IMPL_SET_SOCKET_FLAGS(impl) OS_VxWorks_SetSocketFlags_Impl(impl)

/* The "in.h" header file supplied in VxWorks 6.9 is missing the "in_port_t" typedef */
typedef u_short in_port_t;

/* VxWorks-specific helper function to configure the socket flags on a connection */
void OS_VxWorks_SetSocketFlags_Impl(const OS_object_token_t *token);

#endif /* OS_IMPL_SOCKETS_H */
64 changes: 64 additions & 0 deletions src/os/vxworks/src/os-impl-sockets.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* NASA Docket No. GSC-18,370-1, and identified as "Operating System Abstraction Layer"
*
* Copyright (c) 2019 United States Government as represented by
* the Administrator of the National Aeronautics and Space Administration.
* All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* \file os-impl-sockets.c
* \ingroup vxworks
* \author joseph.p.hickey@nasa.gov
*
*/

/****************************************************************************************
INCLUDE FILES
***************************************************************************************/

#include "os-vxworks.h"
#include "os-shared-idmap.h"
#include "os-impl-io.h"
#include "os-impl-sockets.h"

/****************************************************************************************
INITIALIZATION FUNCTION
***************************************************************************************/

/*----------------------------------------------------------------
*
* Function: OS_VxWorks_ModuleAPI_Impl_Init
*
* Purpose: Local helper routine, not part of OSAL API.
*
*-----------------------------------------------------------------*/
void OS_VxWorks_SetSocketFlags_Impl(const OS_object_token_t *token)
{
OS_impl_file_internal_record_t *impl;
int os_flags;

impl = OS_OBJECT_TABLE_GET(OS_impl_filehandle_table, *token);

/* Use ioctl/FIONBIO on this platform, rather than standard fcntl() */
os_flags = 1;
if (ioctl(impl->fd, FIONBIO, &os_flags) == -1)
{
/* No recourse if ioctl fails - just report the error and move on. */
OS_DEBUG("ioctl(FIONBIO): %s\n", strerror(errno));
}

impl->selectable = true;
}
34 changes: 17 additions & 17 deletions src/unit-test-coverage/portable/src/coveragetest-bsd-sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,34 @@ void Test_OS_SocketOpen_Impl(void)
OS_stream_table[0].socket_type = OS_SocketType_STREAM;
OS_stream_table[0].socket_domain = OS_SocketDomain_INET6;
OSAPI_TEST_FUNCTION_RC(OS_SocketOpen_Impl, (&token), OS_SUCCESS);
UtAssert_True(UT_PortablePosixIOTest_Get_Selectable(token.obj_idx), "Socket is selectable");
}

void Test_OS_SetSocketDefaultFlags_Impl(void)
{
OS_object_token_t token = {0};

/* Failure in fcntl() GETFL */
UT_PortablePosixIOTest_ResetImpl(token.obj_idx);
UT_ResetState(UT_KEY(OCS_fcntl));
UT_SetDeferredRetcode(UT_KEY(OCS_fcntl), 1, -1);
OSAPI_TEST_FUNCTION_RC(OS_SocketOpen_Impl, (&token), OS_SUCCESS);
UtAssert_VOIDCALL(OS_SetSocketDefaultFlags_Impl(&token));
UtAssert_STUB_COUNT(OCS_fcntl, 1);
UtAssert_True(UT_PortablePosixIOTest_Get_Selectable(token.obj_idx), "Socket is selectable");

/* Failure in fcntl() SETFL */
UT_PortablePosixIOTest_ResetImpl(token.obj_idx);
UT_ResetState(UT_KEY(OCS_fcntl));
UT_SetDeferredRetcode(UT_KEY(OCS_fcntl), 2, -1);
OSAPI_TEST_FUNCTION_RC(OS_SocketOpen_Impl, (&token), OS_SUCCESS);
UtAssert_VOIDCALL(OS_SetSocketDefaultFlags_Impl(&token));
UtAssert_STUB_COUNT(OCS_fcntl, 2);
UtAssert_True(UT_PortablePosixIOTest_Get_Selectable(token.obj_idx), "Socket is selectable");

/* Nominal path */
UT_PortablePosixIOTest_ResetImpl(token.obj_idx);
UT_ResetState(UT_KEY(OCS_fcntl));
UtAssert_VOIDCALL(OS_SetSocketDefaultFlags_Impl(&token));
UtAssert_STUB_COUNT(OCS_fcntl, 2);
UtAssert_True(UT_PortablePosixIOTest_Get_Selectable(token.obj_idx), "Socket is selectable");
}

void Test_OS_SocketBind_Impl(void)
Expand Down Expand Up @@ -255,20 +268,6 @@ void Test_OS_SocketAccept_Impl(void)

/* Success case */
OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, 0), OS_SUCCESS);

/* Failure in fcntl() GETFL */
UT_PortablePosixIOTest_ResetImpl(conn_token.obj_idx);
UT_ResetState(UT_KEY(OCS_fcntl));
UT_SetDeferredRetcode(UT_KEY(OCS_fcntl), 1, -1);
OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, 0), OS_SUCCESS);
UtAssert_STUB_COUNT(OCS_fcntl, 1);

/* Failure in fcntl() SETFL */
UT_PortablePosixIOTest_ResetImpl(conn_token.obj_idx);
UT_ResetState(UT_KEY(OCS_fcntl));
UT_SetDeferredRetcode(UT_KEY(OCS_fcntl), 2, -1);
OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, 0), OS_SUCCESS);
UtAssert_STUB_COUNT(OCS_fcntl, 2);
}

void Test_OS_SocketRecvFrom_Impl(void)
Expand Down Expand Up @@ -484,6 +483,7 @@ void Osapi_Test_Teardown(void) {}
void UtTest_Setup(void)
{
ADD_TEST(OS_SocketOpen_Impl);
ADD_TEST(OS_SetSocketDefaultFlags_Impl);
ADD_TEST(OS_SocketBind_Impl);
ADD_TEST(OS_SocketConnect_Impl);
ADD_TEST(OS_SocketShutdown_Impl);
Expand Down
1 change: 1 addition & 0 deletions src/unit-test-coverage/ut-stubs/inc/OCS_ioLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#define OCS_FIOCHKDSK 0x1E01
#define OCS_FIOUNMOUNT 0x1E02
#define OCS_FIONBIO 0x1E03

/* ----------------------------------------- */
/* types normally defined in ioLib.h */
Expand Down
1 change: 1 addition & 0 deletions src/unit-test-coverage/ut-stubs/override_inc/ioLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#define FIOCHKDSK OCS_FIOCHKDSK
#define FIOUNMOUNT OCS_FIOUNMOUNT
#define FIONBIO OCS_FIONBIO
#define ioctl OCS_ioctl

#endif /* OVERRIDE_IOLIB_H */
12 changes: 12 additions & 0 deletions src/unit-test-coverage/ut-stubs/src/os-shared-sockets-impl-stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@
#include "os-shared-sockets.h"
#include "utgenstub.h"

/*
* ----------------------------------------------------
* Generated stub function for OS_SetSocketDefaultFlags_Impl()
* ----------------------------------------------------
*/
void OS_SetSocketDefaultFlags_Impl(const OS_object_token_t *token)
{
UT_GenStub_AddParam(OS_SetSocketDefaultFlags_Impl, const OS_object_token_t *, token);

UT_GenStub_Execute(OS_SetSocketDefaultFlags_Impl, Basic, NULL);
}

/*
* ----------------------------------------------------
* Generated stub function for OS_SocketAccept_Impl()
Expand Down
1 change: 1 addition & 0 deletions src/unit-test-coverage/vxworks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ set(VXWORKS_MODULE_LIST
network
queues
shell
sockets
symtab
tasks
timebase
Expand Down
1 change: 1 addition & 0 deletions src/unit-test-coverage/vxworks/adaptors/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ add_library(ut-adaptor-${SETNAME} STATIC
src/ut-adaptor-mutex.c
src/ut-adaptor-queues.c
src/ut-adaptor-filetable-stub.c
src/ut-adaptor-sockets.c
src/ut-adaptor-symtab.c
src/ut-adaptor-tasks.c
src/ut-adaptor-timebase.c
Expand Down
Loading