📄 rvsocket.c
字号:
RvStatus RVCALLCONV RvSocketSendBuffer(
IN RvSocket* sock,
IN RvUint8* buffer,
IN RvSize_t bytesToSend,
IN RvAddress* remoteAddress,
OUT RvSize_t* bytesSent)
{
RvSocket ourSocket;
RvStatus ret;
int errLen = 0;
int socketError = 0;
ret = RvSocketSharerShare(sock, &ourSocket);
if (ret != RV_OK)
return ret;
if (remoteAddress == NULL)
{
#if (RV_OS_TYPE == RV_OS_TYPE_OSE)
errLen = inet_send(ourSocket, (char *)buffer, (int)bytesToSend, 0);
#elif (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
errLen = NU_Send(ourSocket, (char *)buffer, (int)bytesToSend, 0);
#else
errLen = send(ourSocket, (char *)buffer, (int)bytesToSend, 0);
#endif
}
else
{
RvUint8 sockdata[RV_SOCKET_SOCKADDR_SIZE];
int socklen;
ret = RvSocketAddressToSockAddr(remoteAddress, (RV_SOCKADDR_PTR)sockdata, &socklen);
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
if (ret == RV_OK)
errLen = sendto(ourSocket, (char *)buffer, (int)bytesToSend, 0, (RV_SOCKADDR_PTR)sockdata, socklen);
#else
if (ret == RV_OK)
errLen = NU_Send_To(ourSocket, (char *)buffer, (int)bytesToSend, 0, (RV_SOCKADDR_PTR)sockdata, socklen);
#endif
}
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS) /* (nucleus does not have WOULDBLOCK event) */
if (ret == RV_OK)
{
if (errLen > 0)
{
if (bytesSent != NULL)
*bytesSent = errLen;
}
else
{
/* We had an error - check to see if it's WOULDBLOCK */
socketError = RvSocketErrNo;
if (!RvSocketErrorWouldBlock(socketError))
{
/* An error which is not "Would block" - return an error status */
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
if (bytesSent != NULL)
*bytesSent = 0;
}
}
}
#endif
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_DEBUG)
if (ret == RV_OK)
{
RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
if (remoteAddress != NULL)
RvAddressGetString(remoteAddress, addr, sizeof(addr));
else
addr[0] = '\0';
RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketSendBuffer(sock=%d,addr=%s:%d,buf=0x%p,len=%d,sent=%d)=0",
*sock, addr, RvAddressGetIpPort(remoteAddress), buffer, bytesToSend, errLen));
}
#endif
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ERROR)
if (ret != RV_OK)
{
RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
if (remoteAddress != NULL)
RvAddressGetString(remoteAddress, addr, sizeof(addr));
else
addr[0] = '\0';
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketSendBuffer(sock=%d,addr=%s:%d,buf=0x%p,len=%d,errno=%d)=%d",
*sock, addr, RvAddressGetIpPort(remoteAddress), buffer, bytesToSend, socketError, ret));
}
#endif
RvSocketSharerClose(&ourSocket);
return ret;
}
/********************************************************************************************
* RvSocketReceiveBuffer
*
* purpose : Receive a buffer from a connection
* input : sock - Socket to receive the buffer from
* buffer - Buffer to use for received data
* bytesToReceive - Number of bytes available on the given buffer
* output : bytesReceived - Number of bytes that were actually received
* remoteAddress - Address buffer was received from
* Can be given as NULL on connection-oriented sockets (TCP).
* This address is constructed by this function and should be
* destructed by the caller to this function
* return : RV_OK on success, other on failure
* notes : A blocked socket returns RV_OK with bytesReceived=0
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketReceiveBuffer(
IN RvSocket* sock,
IN RvUint8* buffer,
IN RvSize_t bytesToReceive,
OUT RvSize_t* bytesReceived,
OUT RvAddress* remoteAddress)
{
RvSocket ourSocket;
RvStatus ret;
int errLen;
int socketError = 0;
ret = RvSocketSharerShare(sock, &ourSocket);
if (ret != RV_OK)
return ret;
if (remoteAddress == NULL)
{
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
errLen = recv(ourSocket, (char *)buffer, (int)bytesToReceive, 0);
#else
errLen = NU_Recv(ourSocket, (char *)buffer, (int)bytesToReceive, 0);
#endif
}
else
{
RvUint8 sockdata[RV_SOCKET_SOCKADDR_SIZE];
int socklen = RV_SOCKET_SOCKADDR_SIZE;
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
errLen = recvfrom(ourSocket, (char *)buffer, (int)bytesToReceive, 0, (RV_SOCKADDR_PTR)sockdata, &socklen);
#else
errLen = NU_Recv_From(ourSocket, (char *)buffer, (int)bytesToReceive, 0, (RV_SOCKADDR_PTR)sockdata, (RvInt16*)&socklen);
#endif
if (errLen > 0)
RvSocketSockAddrToAddress(sockdata, socklen, remoteAddress);
}
if (errLen >= 0)
{
if (bytesReceived)
*bytesReceived = (RvSize_t)errLen;
}
else
{
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
/* We had an error - check to see if it's WOULDBLOCK */
socketError = RvSocketErrNo;
if (!RvSocketErrorWouldBlock(socketError))
{
/* An error which is not "Would block" - return an error status */
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
}
#endif
if (bytesReceived)
*bytesReceived = 0;
}
RvSocketSharerClose(&ourSocket);
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_DEBUG)
if (ret == RV_OK)
{
RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
if (remoteAddress != NULL)
RvAddressGetString(remoteAddress, addr, sizeof(addr));
else
addr[0] = '\0';
RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketReceiveBuffer(sock=%d,addr=%s:%d,buf=0x%p,len=%d,received=%d)=0",
*sock, addr, RvAddressGetIpPort(remoteAddress), buffer, bytesToReceive, errLen));
}
#endif
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ERROR)
if (ret != RV_OK)
{
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketReceiveBuffer(sock=%d,buf=0x%p,len=%d,errno=%d)=%d",
*sock, buffer, bytesToReceive, socketError, ret));
}
#endif
return ret;
}
RVCOREAPI
RvStatus RVCALLCONV RvSocketSetBuffers(IN RvSocket *sock, IN RvInt32 sendSize, IN RvInt32 recvSize)
{
RvSocket ourSocket;
RvStatus ret = RvSocketErrorCode(RV_ERROR_NOTSUPPORTED);
int buflen=0;
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS) /* can't set buffer sizes in nucleus */
ret = RvSocketSharerShare(sock, &ourSocket);
if (ret != RV_OK)
return ret;
if (recvSize >= 0)
{
buflen = (int)recvSize;
if (RvSocketSetSockOpt(&ourSocket, SOL_SOCKET, SO_RCVBUF, (char*)&buflen, sizeof(buflen)) != 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
}
if (sendSize >= 0)
{
buflen = (int)sendSize;
if (RvSocketSetSockOpt(&ourSocket, SOL_SOCKET, SO_SNDBUF, (char*)&buflen, sizeof(buflen)) != 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
}
RvSocketSharerClose(&ourSocket);
#endif
return ret;
}
/********************************************************************************************
* RvSocketSetLinger
*
* purpose : Set the linger time after socket is closed.
* input : sock - Socket to modify
* lingerTime - Time to linger in seconds
* Setting this parameter to -1 sets linger off for this socket
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketSetLinger(IN RvSocket *sock, IN RvInt32 lingerTime)
{
#if (RV_OS_TYPE == RV_OS_TYPE_OSE) || (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
/* Linger parameter of a socket is not supported in OSE & NUCLEUS */
return RvSocketErrorCode(RV_ERROR_NOTSUPPORTED);
#else
RvStatus status = RV_OK;
struct linger lingerParam;
if (lingerTime >= 0)
{
lingerParam.l_onoff = RV_TRUE;
lingerParam.l_linger = (RV_LINGER_VALUE_TYPE)lingerTime;
}
else
{
lingerParam.l_onoff = RV_FALSE;
lingerParam.l_linger = 0;
}
if (RvSocketSetSockOpt(sock, SOL_SOCKET, SO_LINGER, (char *)&lingerParam, sizeof(lingerParam)) != 0)
{
status = RvSocketErrorCode(RV_ERROR_UNKNOWN);
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketSetLinger(sock=%d,linger=%d,errno=%d)=%d",
*sock, lingerTime, RvSocketErrNo, status));
}
return status;
#endif
}
/********************************************************************************************
* RvSocketReuseAddr
*
* purpose : Set the socket as a reusable one (in terms of its address)
* This allows a TCP server socket and UDP multicast addresses to be used by
* other processes on the same machine as well.
* This function has to be called before RvSocketBind().
* input : sock - Socket to modify
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketReuseAddr(IN RvSocket *sock)
{
#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
/* Reuse address parameter of a socket is not supported in NUCLEUS */
return RvSocketErrorCode(RV_ERROR_NOTSUPPORTED);
#else
RvStatus ret = RV_OK;
int yes = RV_TRUE;
if (RvSocketSetSockOpt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) != 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
return ret;
#endif
}
/********************************************************************************************
* RvSocketSetBlocking
*
* purpose : Set blocking/non-blocking mode on a socket
* input : sock - Socket to modify
* isBlocking - RV_TRUE for a blocking socket
* RV_FALSE for a non-blocking socket
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketSetBlocking(IN RvSocket *sock, IN RvBool isBlocking)
{
RvSocket ourSocket;
RvStatus status;
int res;
status = RvSocketSharerShare(sock, &ourSocket);
if (status != RV_OK)
return status;
#if (RV_SOCKET_TYPE == RV_SOCKET_WIN32_WSA)
{
RV_IOCTL_ARGP_TYPE on = !isBlocking;
res = ioctlsocket(ourSocket, FIONBIO, &on);
}
#elif (RV_SOCKET_TYPE == RV_SOCKET_NUCLEUS)
if (isBlocking)
res = NU_Fcntl(ourSocket, NU_SETFLAG, NU_BLOCK);
else
res = NU_Fcntl(ourSocket, NU_SETFLAG, NU_FALSE);
#else
{
RV_IOCTL_ARGP_TYPE on = !isBlocking;
res = ioctl(ourSocket, FIONBIO, (RV_IOCTL_ARGP_TYPE*) &on);
}
#endif
if (res < 0)
status = RvSocketErrorCode(RV_ERROR_UNKNOWN);
RvSocketSharerClose(&ourSocket);
return status;
}
/********************************************************************************************
* RvSocketSetBroadcast
*
* purpose : Set permission for sending broadcast datagrams on a socket
* input : sock - Socket to modify
* canBroadcast - RV_TRUE for permitting broadcast
* RV_FALSE for not permitting broadcast
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketSetBroadcast(IN RvSocket *sock, IN RvBool canBroadcast)
{
RvStatus ret = RV_OK;
int on = (int)canBroadcast;
if (RvSocketSetSockOpt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) != 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
return ret;
}
/********************************************************************************************
* RvSocketSetMulticastTtl
*
* purpose : Set the TTL to use for multicast sockets (UDP)
* input : sock - Socket to modify
* ttl - TTL to set
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketSetMulticastTtl(IN RvSocket *sock, IN RvInt32 ttl)
{
RvStatus ret = RV_OK;
#if RV_SOCKET_HAS_IPV6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -