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 #960, add socket shutdown implementation #976

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
1 change: 1 addition & 0 deletions src/os/inc/osapi-error.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ typedef char os_err_name_t[OS_ERROR_NAME_LENGTH];
#define OS_ERR_OPERATION_NOT_SUPPORTED (-38) /**< @brief Requested operation not support on supplied object(s) */
#define OS_ERR_INVALID_SIZE (-40) /**< @brief Invalid Size */
#define OS_ERR_OUTPUT_TOO_LARGE (-41) /**< @brief Size of output exceeds limit */
#define OS_ERR_INVALID_ARGUMENT (-42) /**< @brief Invalid argument value (other than ID or size) */

/*
** Defines for File System Calls
Expand Down
24 changes: 24 additions & 0 deletions src/os/inc/osapi-sockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ typedef enum
OS_SocketType_MAX /**< @brief Maximum */
} OS_SocketType_t;

/* NOTE: The shutdown mode enums are also a bitmask, so the specific values are important here */
/** @brief Shutdown Mode */
typedef enum
{
OS_SocketShutdownMode_NONE = 0, /**< @brief Reserved value, no effect */
OS_SocketShutdownMode_SHUT_READ = 1, /**< @brief Disable future reading */
OS_SocketShutdownMode_SHUT_WRITE = 2, /**< @brief Disable future writing */
OS_SocketShutdownMode_SHUT_READWRITE = 3 /**< @brief Disable future reading or writing */
} OS_SocketShutdownMode_t;

/**
* @brief Storage buffer for generic network address
*
Expand Down Expand Up @@ -279,6 +289,20 @@ int32 OS_SocketBind(osal_id_t sock_id, const OS_SockAddr_t *Addr);
*/
int32 OS_SocketConnect(osal_id_t sock_id, const OS_SockAddr_t *Addr, int32 timeout);

/*-------------------------------------------------------------------------------------*/
/**
* @brief Implement graceful shutdown of a stream socket
*
* This can be utilized to indicate the end of data stream without immediately closing
* the socket, giving the remote side an indication that the data transfer is complete.
*
* @param[in] sock_id The socket ID
* @param[in] Mode Whether to shutdown reading, writing, or both.
*
* @return Execution status, see @ref OSReturnCodes
*/
int32 OS_SocketShutdown(osal_id_t sock_id, OS_SocketShutdownMode_t Mode);

/*-------------------------------------------------------------------------------------*/
/**
* @brief Waits for and accept the next incoming connection on the given socket
Expand Down
43 changes: 43 additions & 0 deletions src/os/portable/os-impl-bsd-sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,49 @@ int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t
return return_code;
} /* end OS_SocketConnect_Impl */

/*----------------------------------------------------------------
Function: OS_SocketShutdown_Impl

Purpose: Connects the socket to a remote address.
Socket must be of the STREAM variety.

Returns: OS_SUCCESS on success, or relevant error code
------------------------------------------------------------------*/
int32 OS_SocketShutdown_Impl(const OS_object_token_t *token, OS_SocketShutdownMode_t Mode)
{
OS_impl_file_internal_record_t *conn_impl;
int32 return_code;
int how;

conn_impl = OS_OBJECT_TABLE_GET(OS_impl_filehandle_table, *token);

/* Note that when called via the shared layer,
* the "Mode" arg has already been checked/validated. */
if (Mode == OS_SocketShutdownMode_SHUT_READ)
{
how = SHUT_RD;
}
else if (Mode == OS_SocketShutdownMode_SHUT_WRITE)
{
how = SHUT_WR;
}
else
{
how = SHUT_RDWR;
}

if (shutdown(conn_impl->fd, how) == 0)
{
return_code = OS_SUCCESS;
}
else
{
return_code = OS_ERROR;
}

return return_code;
} /* end OS_SocketShutdown_Impl */

/*----------------------------------------------------------------
*
* Function: OS_SocketAccept_Impl
Expand Down
10 changes: 10 additions & 0 deletions src/os/portable/os-impl-no-sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t
return OS_ERR_NOT_IMPLEMENTED;
}

/*----------------------------------------------------------------
* Implementation for no network configuration
*
* See prototype for argument/return detail
*-----------------------------------------------------------------*/
int32 OS_SocketShutdown_Impl(const OS_object_token_t *token, OS_SocketShutdownMode_t Mode)
{
return OS_ERR_NOT_IMPLEMENTED;
}

/*----------------------------------------------------------------
* Implementation for no network configuration
*
Expand Down
1 change: 1 addition & 0 deletions src/os/posix/inc/os-impl-sockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#define OS_NETWORK_SUPPORTS_IPV6

Expand Down
9 changes: 9 additions & 0 deletions src/os/shared/inc/os-shared-sockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_
------------------------------------------------------------------*/
int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t *Addr, int32 timeout);

/*----------------------------------------------------------------
Function: OS_SocketShutdown_Impl

Purpose: Graceful shutdown of a stream socket

Returns: OS_SUCCESS on success, or relevant error code
------------------------------------------------------------------*/
int32 OS_SocketShutdown_Impl(const OS_object_token_t *token, OS_SocketShutdownMode_t Mode);

/*----------------------------------------------------------------
Function: OS_SocketRecvFrom_Impl

Expand Down
56 changes: 56 additions & 0 deletions src/os/shared/src/osapi-sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,62 @@ int32 OS_SocketConnect(osal_id_t sock_id, const OS_SockAddr_t *Addr, int32 Timeo
return return_code;
} /* end OS_SocketConnect */

/*----------------------------------------------------------------
*
* Function: OS_SocketShutdown
*
* Purpose: Implemented per public OSAL API
* See description in API and header file for detail
*
*-----------------------------------------------------------------*/
int32 OS_SocketShutdown(osal_id_t sock_id, OS_SocketShutdownMode_t Mode)
{
OS_stream_internal_record_t *stream;
OS_object_token_t token;
int32 return_code;

/* Confirm that "Mode" is one of the 3 acceptable values */
BUGCHECK(Mode == OS_SocketShutdownMode_SHUT_READ || Mode == OS_SocketShutdownMode_SHUT_WRITE ||
Mode == OS_SocketShutdownMode_SHUT_READWRITE,
OS_ERR_INVALID_ARGUMENT);

return_code = OS_ObjectIdGetById(OS_LOCK_MODE_GLOBAL, LOCAL_OBJID_TYPE, sock_id, &token);
if (return_code == OS_SUCCESS)
{
stream = OS_OBJECT_TABLE_GET(OS_stream_table, token);

if (stream->socket_domain == OS_SocketDomain_INVALID)
{
return_code = OS_ERR_INCORRECT_OBJ_TYPE;
}
else if (stream->socket_type == OS_SocketType_STREAM && (stream->stream_state & OS_STREAM_STATE_CONNECTED) == 0)
{
/* Stream socket must not be connected */
return_code = OS_ERR_INCORRECT_OBJ_STATE;
}
else
{
return_code = OS_SocketShutdown_Impl(&token, Mode);

if (return_code == OS_SUCCESS)
{
if (Mode & OS_SocketShutdownMode_SHUT_READ)
{
stream->stream_state &= ~OS_STREAM_STATE_READABLE;
}
if (Mode & OS_SocketShutdownMode_SHUT_WRITE)
{
stream->stream_state &= ~OS_STREAM_STATE_WRITABLE;
}
}
}

OS_ObjectIdRelease(&token);
}

return return_code;
} /* end OS_SocketShutdown */

/*----------------------------------------------------------------
*
* Function: OS_SocketRecvFrom
Expand Down
Loading