📄 rvsocket.c
字号:
* NULL if this parameter should be ignored.
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketBind(
IN RvSocket* sock,
IN RvAddress* address,
IN RvPortRange* portRange)
{
RvStatus ret;
RvSocket ourSocket = 0;
RvUint8 sockdata[RV_SOCKET_SOCKADDR_SIZE];
int socklen;
RvBool usePortRange;
#if (RV_SOCKET_TYPE == RV_SOCKET_NUCLEUS)
/* In NUCLEUS, we make sure to have a portRange. If none is supplied, we just use
the static one declared and used in this module. */
if (portRange == NULL)
portRange = &RvSocketPortRange;
#endif
usePortRange = ((portRange != NULL) &&
(RvAddressGetIpPort(address) == RV_ADDRESS_IPV4_ANYPORT));
ret = RvSocketAddressToSockAddr(address, (RV_SOCKADDR_PTR)sockdata, &socklen);
if (ret == RV_OK)
ret = RvSocketSharerShare(sock, &ourSocket);
if (ret == RV_OK)
{
if (usePortRange)
{
RvUint numberOfTries, port;
ret = RvPortRangeGetNumberOfFreePorts(portRange, &numberOfTries);
/* Try until we went through all available ports or until we find a vacant port */
while ((numberOfTries > 0) && (ret == RV_OK))
{
/* Get a port */
ret = RvPortRangeGetPort(portRange, &port);
if (ret != RV_OK)
break;
/* Fix port in address struct */
ret = RvSocketSockAddrSetPort((RV_SOCKADDR_PTR)sockdata, port);
if (ret != RV_OK)
break;
/* Try to bind */
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
if ((bind(ourSocket, (RV_SOCKADDR_PTR)sockdata, socklen)) >= 0)
break; /* We found a good one - exit the while loop */
#else
if (NU_Bind(ourSocket, (struct sockaddr_in *)sockdata, 0) < 0)
break; /* We found a good one - exit the while loop */
#endif
/* Check the error code to see if we want to resume our check */
#if (RV_SOCKET_TYPE == RV_SOCKET_WIN32_WSA)
switch (WSAGetLastError())
{
case WSAEACCES:
case WSAEADDRINUSE:
case WSAEADDRNOTAVAIL:
/* We assume that adress is in use even if it's unavailable or we have an access violation */
break;
default:
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
break;
}
#elif (RV_SOCKET_TYPE == RV_SOCKET_BSD)
switch (RvSocketErrNo)
{
case EADDRINUSE:
case EADDRNOTAVAIL:
#ifdef EACCES
case EACCES: /* Not supported in WinCE or PSOS */
#endif
/* We assume that adress is in use even if it's unavailable or we have an access violation */
break;
default:
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
break;
}
#endif
/* No good - this port is taken by someone other than this port range. Release
this port back to pool of free ports - it might get free next time. */
RvPortRangeReleasePort(portRange, port);
numberOfTries--;
}
}
else
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
/* Just bind and get it over with */
if ((bind(ourSocket, (RV_SOCKADDR_PTR)sockdata, socklen)) < 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#else
if ((NU_Bind(ourSocket, (struct sockaddr_in *)sockdata, socklen)) < 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#endif
}
RvSocketSharerClose(&ourSocket);
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_DEBUG)
if (ret == RV_OK)
{
RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
RvAddressGetString(address, addr, sizeof(addr));
RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketBind(sock=%d,addr=%s:%d,range=0x%p,useRange=%d)=0",
*sock, addr, RvAddressGetIpPort(address), portRange, usePortRange));
}
#endif
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ERROR)
if (ret != RV_OK)
{
RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
RvAddressGetString(address, addr, sizeof(addr));
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketBind(sock=%d,addr=%s:%d,range=0x%p,useRange=%d,errno=%d)=%d",
*sock, addr, RvAddressGetIpPort(address), portRange, usePortRange, RvSocketErrNo, ret));
}
#endif
return ret;
}
/* =========================== */
/* ==== functions for TCP ==== */
/* =========================== */
RVCOREAPI
RvStatus RVCALLCONV RvSocketConnect(IN RvSocket *sock, IN RvAddress* address)
{
RvSocket ourSocket;
RvStatus ret;
RvUint8 sockdata[RV_SOCKET_SOCKADDR_SIZE];
int socklen;
ret = RvSocketAddressToSockAddr(address, (RV_SOCKADDR_PTR)sockdata, &socklen);
if (ret != RV_OK)
return ret;
ret = RvSocketSharerShare(sock, &ourSocket);
if (ret != RV_OK)
return ret;
#if (RV_SOCKET_TYPE == RV_SOCKET_BSD) /* B S D */
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS) /* B S D - All OS */
if (connect(ourSocket, (RV_SOCKADDR_PTR)sockdata, socklen) != 0)
{
/* Make sure the error is not due to the non-blocking nature of this socket */
if (RvSocketErrNo != EINPROGRESS)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
}
#else /* B S D - Nucleus */
/* Set timer to 45s connection time */
ret = RvTimerStart(nuConInfo[ourSocket].timer, timerQueue,
RV_TIMER_TYPE_ONESHOT, 45000 /* 45 seconds */,
RvSocketEvTimerExp, ourSocket);
if (ret != RV_OK)
{
/* print log */
return RvSocketErrorCode(RV_ERROR_UNKNOWN);
}
nuConInfo[ourSocket].sockAddress = *address;
RvThreadConstruct(&nuConInfo[ourSocket].threadId, RvSocketEventsTask, ourSocket);
nuConInfo[ourSocket].socketState = RvSocketState_Connecting;
ret = RvThreadStart(nuConInfo[ourSocket].threadId);
if (ret != RV_OK)
{
nuConInfo[ourSocket].socketState == RvSocketState_Idle;
return RvSocketErrorCode(RV_ERROR_UNKNOWN);
}
else
nuConInfo[ourSocket].socketState == RvThreadState_Running;
#endif
#elif (RV_SOCKET_TYPE == RV_SOCKET_WIN32_WSA)
if (WSAConnect(ourSocket, (RV_SOCKADDR_PTR)sockdata, socklen, NULL, NULL, NULL, NULL) == SOCKET_ERROR)
{
/* Would-Block error is just fine with us... */
int wsaError = WSAGetLastError();
if (wsaError != WSAEWOULDBLOCK)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
}
#endif
RvSocketSharerClose(&ourSocket);
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_DEBUG)
if (ret == RV_OK)
{
RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
RvAddressGetString(address, addr, sizeof(addr));
RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketConnect(sock=%d,addr=%s:%d)=0",
*sock, addr, RvAddressGetIpPort(address)));
}
#endif
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ERROR)
if (ret != RV_OK)
{
RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
RvAddressGetString(address, addr, sizeof(addr));
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketConnect(sock=%d,addr=%s:%d,errno=%d)=%d",
*sock, addr, RvAddressGetIpPort(address), RvSocketErrNo, ret));
}
#endif
return ret;
}
/********************************************************************************************
* RvSocketAccept
*
* purpose : Accept an incoming socket request
* input : sock - Listening socket receiving the incoming connection
* output : newSocket - Accepted socket information
* remoteAddress - Address of remote side of connection
* Can be passed as NULL if not needed
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketAccept(
IN RvSocket* sock,
OUT RvSocket* newSocket,
OUT RvAddress* remoteAddress)
{
RvSocket ourSocket;
RvStatus ret;
RvUint8 sockdata[RV_SOCKET_SOCKADDR_SIZE];
int socklen = RV_SOCKET_SOCKADDR_SIZE;
ret = RvSocketSharerShare(sock, &ourSocket);
if (ret != RV_OK)
return ret;
#if (RV_SOCKET_TYPE == RV_SOCKET_BSD)
#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
if ((*newSocket = NU_Accept(ourSocket, (RV_SOCKADDR_PTR)sockdata, 0)) < 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
/* check socket state - if still idle, close it in its task */
if (nuConInfo[*newSocket].socketState)
{
RvSocketTaskClean(*newSocket);
RvSocketCallback(*newSocket,RV_SELECT_CLOSE);
}
memset(nuConInfo+(*newSocket),0,sizeof(nuConInfo[*newSocket]));
nuConInfo[*newSocket].socketState = RvSocketState_Connected;
#else
if ((*newSocket = accept(ourSocket, (RV_SOCKADDR_PTR)sockdata, &socklen)) < 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#endif
if (ret == RV_OK)
{
/* Some Unix systems don't like setting the options of the listening socket in the
accepted one, so we have to change the defaults to fit the regular needs. */
int yes = RV_TRUE;
/* Disable Nagle algorithm - we want our messages to be sent as soon as possible */
if (RvSocketSetSockOpt(newSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(yes)) != 0)
{
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketAccept: Failed to setsockopt(TCP_NODELAY) %d",
RvSocketErrNo));
}
/* We're working with non-blocking sockets */
RvSocketSetBlocking(newSocket, RV_FALSE);
}
#elif (RV_SOCKET_TYPE == RV_SOCKET_WIN32_WSA)
*newSocket = WSAAccept(ourSocket, (RV_SOCKADDR_PTR)&sockdata, &socklen, NULL, 0);
if ((*newSocket) == INVALID_SOCKET)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#endif
RvSocketSharerClose(&ourSocket);
if ((ret == RV_OK) && (remoteAddress != NULL))
ret = RvSocketSockAddrToAddress(sockdata, socklen, remoteAddress);
#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,
"RvSocketAccept(sock=%d,new=%d,addr=%s:%d)=0",
*sock, *newSocket, addr, RvAddressGetIpPort(remoteAddress)));
}
#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,
"RvSocketAccept(sock=%d,new=%d,addr=%s:%d,errno=%d)=%d",
*sock, *newSocket, addr, RvAddressGetIpPort(remoteAddress), RvSocketErrNo, ret));
}
#endif
return ret;
}
/********************************************************************************************
* RvSocketListen
*
* purpose : Waits for an incoming connection.
* input : sock - Listening socket receiving the incoming connection
* queuelen -
* output : None.
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketListen(IN RvSocket *sock, IN RvUint32 queuelen)
{
RvSocket ourSocket;
RvStatus ret;
ret = RvSocketSharerShare(sock, &ourSocket);
if (ret != RV_OK)
return ret;
#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
if (NU_Listen(ourSocket, (int)queuelen) < 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
ret = RvSocketSetBlocking(&ourSocket, RV_FALSE);
#else
if (listen(ourSocket, (int)queuelen) < 0)
ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#endif
RvSocketSharerClose(&ourSocket);
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_DEBUG)
if (ret == RV_OK)
{
RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketListen(sock=%d,len=%d)=0",
*sock, queuelen));
}
#endif
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ERROR)
if (ret != RV_OK)
{
RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
"RvSocketConnect(sock=%d,len=%d,errno=%d)=%d",
*sock, queuelen, RvSocketErrNo, ret));
}
#endif
return ret;
}
/********************************************************************************************
* RvSocketSendBuffer
*
* purpose : Send a buffer on a connection
* input : sock - Socket to send the buffer on
* buffer - Buffer to send
* bytesToSend - Number of bytes to send from buffer
* remoteAddress - Address to send the buffer to.
* Can be NULL on connection-oriented sockets (TCP).
* output : bytesSent - Number of bytes we sent
* If less than bytesToSend, then we would block if we tried on a
* blocking socket. The application in this cas should wait for a
* WRITE event before trying again.
* return : RV_OK on success, other on failure
* notes : A blocked socket returns RV_OK with bytesSent=0
********************************************************************************************/
RVCOREAPI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -