📄 rvsocket.c
字号:
res = RvSemaphoreConstruct(&RvSharer.requestSem, RvUint32Const(0));
if (res != RV_OK)
{
RvLockDestruct(&RvSharer.lock);
return res;
}
res = RvSemaphoreConstruct(&RvSharer.responseSem, RvUint32Const(0));
if (res != RV_OK)
{
RvSemaphoreDestruct(&RvSharer.requestSem);
RvLockDestruct(&RvSharer.lock);
return res;
}
res = RvThreadConstruct(&RvSharer.thread, RvSocketSharerThread, &RvSharer);
if (res != RV_OK)
{
RvSemaphoreDestruct(&RvSharer.responseSem);
RvSemaphoreDestruct(&RvSharer.requestSem);
RvLockDestruct(&RvSharer.lock);
return res;
}
/* Create and start the sharer thread. */
res = RvThreadCreate(&RvSharer.thread);
if (res == RV_OK)
res = RvThreadStart(&RvSharer.thread);
if (res != RV_OK)
{
RvThreadDestruct(&RvSharer.thread);
RvSemaphoreDestruct(&RvSharer.responseSem);
RvSemaphoreDestruct(&RvSharer.requestSem);
RvLockDestruct(&RvSharer.lock);
}
return res;
}
static RvStatus RvSocketSharerEnd(void)
{
/* Make sure we exit the sharer thread */
RvLockGet(&RvSharer.lock);
RvSharer.cmd.command = RvSocketSharerCommandExit; /* Post an exit request */
if (RvSemaphorePost(&RvSharer.requestSem) == RV_OK)
RvSemaphoreWait(&RvSharer.responseSem);
RvThreadDestruct(&RvSharer.thread);
RvSemaphoreDestruct(&RvSharer.responseSem);
RvSemaphoreDestruct(&RvSharer.requestSem);
RvLockDestruct(&RvSharer.lock);
return RV_OK;
}
/********************************************************************************************
* RvSocketSharerConstruct
*
* purpose : Construct a socket using the socket sharer
* input : sock - Socket to construct
* addressType - Type of address to create
* protocolType - Type of protocol used by the socket
* return : RV_OK on success, other on failure
********************************************************************************************/
static RvStatus RvSocketSharerConstruct(
IN RvSocket* sock,
IN RvAddressType addressType,
IN RvSocketProtocol protocolType)
{
RvStatus res;
RvSharer.cmd.command = RvSocketSharerCommandCreate;
RvSharer.cmd.socket = sock;
RvSharer.cmd.addressType = addressType;
RvSharer.cmd.protocolType = protocolType;
/* Send command to the sharer thread */
res = RvLockGet(&RvSharer.lock);
if (res != RV_OK)
return res;
res = RvSemaphorePost(&RvSharer.requestSem);
if (res == RV_OK)
res = RvSemaphoreWait(&RvSharer.responseSem);
if (res == RV_OK)
res = (RvStatus)RvSharer.result;
RvLockRelease(&RvSharer.lock);
return res;
}
static RvStatus RvSocketSharerDestruct(IN RvSocket* sock)
{
RvStatus res;
RvSharer.cmd.command = RvSocketSharerCommandDestroy;
RvSharer.cmd.socket = sock;
/* Send command to the sharer thread */
res = RvLockGet(&RvSharer.lock);
if (res != RV_OK)
return res;
res = RvSemaphorePost(&RvSharer.requestSem);
if (res == RV_OK)
res = RvSemaphoreWait(&RvSharer.responseSem);
if (res == RV_OK)
res = (RvStatus)RvSharer.result;
RvLockRelease(&RvSharer.lock);
return res;
}
static RvStatus RvSocketSharerShare(IN RvSocket* sock, OUT RvSocket* sharableSocket)
{
RvStatus res;
RvSharer.cmd.command = RvSocketSharerCommandShare;
RvSharer.cmd.socket = sock;
RvSharer.cmd.task = RvThreadCurrentId();
RvSharer.cmd.sharableSocket = sharableSocket;
/* Send command to the sharer thread */
res = RvLockGet(&RvSharer.lock);
if (res != RV_OK)
return res;
res = RvSemaphorePost(&RvSharer.requestSem);
if (res == RV_OK)
res = RvSemaphoreWait(&RvSharer.responseSem);
if (res == RV_OK)
res = (RvStatus)RvSharer.result;
RvLockRelease(&RvSharer.lock);
return res;
}
/* todo: open commented part! */
#define RvSocketSharerClose(_sock) /*close(*(_sock))*/
static int RvSocketSetSockOpt(
IN RvSocket* socket,
IN int level,
IN int optName,
IN const char* optVal,
IN int optLen)
{
RvSocket ourSocket;
RvStatus status;
int res;
status = RvSocketSharerShare(socket, &ourSocket);
if (status != RV_OK)
return -1;
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
res = setsockopt(ourSocket, level, optName, optVal, optLen);
#else
res = NU_Setsockopt(ourSocket, level, optName, optVal, optLen);
#endif
RvSocketSharerClose(&ourSocket);
return res;
}
#else
/* (RV_SOCKET_USE_SHARER == 0) */
#define RvSocketSharerInit() RV_OK
#define RvSocketSharerEnd() RV_OK
#define RvSocketSharerConstruct(_sock, _addressType, _protocolType) RV_OK
#define RvSocketSharerDestruct(_sock) RV_OK
#define RvSocketSharerShare(_sock, _sharableSock) (*(_sharableSock) = *(_sock)) ? RV_OK : RV_OK
#define RvSocketSharerClose(_sock)
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
#define RvSocketSetSockOpt(_sock, _level, _optName, _optVal, _optLen) \
setsockopt(*(_sock), (_level), (_optName), (_optVal), (_optLen))
#else
#define RvSocketSetSockOpt(_sock, _level, _optName, _optVal, _optLen) \
NU_Setsockopt(*(_sock), (_level), (_optName), (_optVal), (_optLen))
#endif
#endif /* (RV_SOCKET_USE_SHARER == 1) */
/********************************************************************************************
*
* Private functions
*
********************************************************************************************/
#if (RV_SOCKET_TYPE == RV_SOCKET_BSD)
/* Handler for SIGPIPE signals. We get these when TCP connections tear down in a non-graceful
manner. Their default behavior in Unix is a core dump, so we put in place this signal
handler that just ignores this signal. */
#if (RV_OS_TYPE != RV_OS_TYPE_WINCE) && (RV_OS_TYPE != RV_OS_TYPE_OSE)
static void RvSocketHandleSigPipe(IN int sigNo)
{
sigNo = 0;
/* Reset this signal */
signal(SIGPIPE, RvSocketHandleSigPipe);
}
#endif /* (RV_OS_TYPE != RV_OS_TYPE_WINCE) */
#endif /* (RV_SOCKET_TYPE == RV_SOCKET_BSD) */
/********************************************************************************************
* RvSocketConstructHere
*
* purpose : Create a socket handle here. This function is internal, since some operating
* systems such as pSOS needs to create the socket in a specified thread, other than
* the one that called RvSocketConstruct()
* input : sock - Socket to construct
* addressType - Type of address to create
* protocolType - Protocol to use with socket
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
static RvStatus RvSocketConstructHere(
IN RvSocket* sock,
IN RvInt addressType,
IN RvSocketProtocol protocolType)
{
int addressFamily = 0;
RvStatus status = RV_OK;
switch (addressType)
{
case RV_ADDRESS_TYPE_IPV4:
addressFamily = AF_INET;
break;
#if RV_SOCKET_HAS_IPV6
case RV_ADDRESS_TYPE_IPV6:
addressFamily = AF_INET6;
break;
#endif
default:
return RvSocketErrorCode(RV_ERROR_BADPARAM);
}
#if (RV_SOCKET_TYPE == RV_SOCKET_WIN32_WSA)
*sock = WSASocket(addressFamily, rvSocketProtocolInfo[protocolType].protocolType,
rvSocketProtocolInfo[protocolType].protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
if ((*sock) == INVALID_SOCKET)
status = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#elif ((RV_SOCKET_TYPE == RV_SOCKET_BSD) || (RV_SOCKET_TYPE == RV_SOCKET_PSOS))
if ((*sock = socket(addressFamily, rvSocketProtocolInfo[protocolType].protocolType,
rvSocketProtocolInfo[protocolType].protocol)) < 0)
status = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#elif (RV_SOCKET_TYPE == RV_SOCKET_NUCLEUS)
if ((*sock = NU_Socket(addressFamily, rvSocketProtocolInfo[protocolType].protocolType,
rvSocketProtocolInfo[protocolType].protocol)) < 0)
status = RvSocketErrorCode(RV_ERROR_UNKNOWN);
/* make sure there's no old socket still open here */
if (nuConInfo[*sock].socketState!=0)
{
RvSocketTaskClean(*sock);
RvSocketCallback(*sock, RV_SELECT_CLOSE);
}
memset(nuConInfo+(*sock), 0, sizeof(nuConInfo[*sock]));
#endif
if (status == RV_OK)
{
if (protocolType == RvSocketProtocolTcp)
{
int yes = RV_TRUE;
#if (RV_OS_TYPE == RV_OS_TYPE_WIN32) || (RV_OS_TYPE == RV_OS_TYPE_WINCE)
/* Set linger parameter of the socket. On Windows, we'll disable it. */
RvSocketSetLinger(sock, -1);
#else
/* On other operating systems - we set the linger timeout to 0 */
RvSocketSetLinger(sock, 0);
#endif
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS) /* no support for KEEP-ALIVE in nucleus */
/* Make sure the TCP connection sends keep-alive messages once in a while */
if (RvSocketSetSockOpt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&yes, sizeof(yes)) != 0)
{
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketConstructHere: Failed to setsockopt(SO_KEEPALIVE) %d",
RvSocketErrNo));
}
#endif
/* Disable Nagle algorithm - we want our messages to be sent as soon as possible */
if (RvSocketSetSockOpt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(yes)) != 0)
{
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketConstructHere: Failed to setsockopt(TCP_NODELAY) %d",
RvSocketErrNo));
}
}
}
else
{
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketConstructHere: Failed to call socket() - %d", RvSocketErrNo));
}
return RV_OK;
}
/********************************************************************************************
* RvSocketSockAddrToAddress
*
* purpose : Convert a sockaddr struct into an RvAddress struct.
* input : sockaddr - Socket address
* socklen - Socket address length
* output : address - Address constructed
* return : RV_OK on success, other on failure
********************************************************************************************/
static RvStatus RvSocketSockAddrToAddress(
IN RvUint8* sockaddr,
IN int socklen,
OUT RvAddress* address)
{
RV_UNUSED_ARG(socklen);
switch (((struct sockaddr_in*)sockaddr)->sin_family)
{
case AF_INET:
{
struct sockaddr_in* sin = (struct sockaddr_in *)sockaddr;
RvAddressConstructIpv4(address,
(RvUint32)sin->sin_addr.s_addr, ntohs(sin->sin_port));
}
break;
#if RV_SOCKET_HAS_IPV6
case AF_INET6:
{
struct sockaddr_in6* sin = (struct sockaddr_in6*)sockaddr;
return RvAddressConstructIpv6(address, sin->sin6_addr,
ntohs(sin->sin6_port),
sin->sin6_flowinfo, sin->sin6_scope_id);
}
break;
#endif /* RV_SOCKET_HAS_IPV6 */
default:
return RvSocketErrorCode(RV_ERROR_NOTSUPPORTED);
}
return RV_OK;
}
/********************************************************************************************
* RvSocketAddressToSockAddr
*
* purpose : Convert an RvAddress struct into a sockaddr struct.
* input : address - Address to convert
* output : sockaddr - Socket address constructed
* socklen - Socket address length constructed
* return : RV_OK on success, other on failure
********************************************************************************************/
static RvStatus RvSocketAddressToSockAddr(
IN RvAddress* address,
OUT RV_SOCKADDR_PTR sockaddr,
OUT int* socklen)
{
RvStatus res = RV_OK;
switch (RvAddressGetType(address))
{
case RV_ADDRESS_TYPE_IPV4:
{
struct sockaddr_in* sin = (struct sockaddr_in *)sockaddr;
const RvAddressIpv4* ipv4Addr;
ipv4Addr = RvAddressGetIpv4(address);
if (ipv4Addr != NULL)
{
memset(sin, 0, sizeof(struct sockaddr_in));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -