📄 sockets.c
字号:
sockets[socketIndex].mIsActive=0;
ASSIGN_SIGNATURE(&(sockets[socketIndex]),0);
smsc_semaphore_signal(&gSocketsLock);
}
static struct SOCKET * get_socket(int socketIndex)
{
struct SOCKET * socket=NULL;
SMSC_ASSERT(socketIndex>=0);
SMSC_ASSERT(socketIndex<MAXIMUM_NUMBER_OF_SOCKETS);
socket=&(sockets[socketIndex]);
SMSC_ASSERT(socket->mIsActive);
return socket;
}
int smsc_socket(int domain, int type, int protocol)
{
int socketIndex=-1;
struct SOCKET * socket=NULL;
socketIndex=alloc_socket();
if (socketIndex == -1) {
set_errno(ENOBUFS);
goto ERROR;
}
socket=get_socket(socketIndex);
switch(type) {
case SOCK_RAW:
SMSC_ERROR(("smsc_socket: Raw sockets are not supported"));
set_errno(EINVAL);
goto ERROR;
#if UDP_ENABLED
case SOCK_DGRAM:
if(SocketRequest_CreateUdpControlBlock(socket)!=0) {
set_errno(ENOBUFS);
goto ERROR;
}
break;
#endif
#if TCP_ENABLED
case SOCK_STREAM:
if(SocketRequest_CreateTcpControlBlock(socket)!=0) {
set_errno(ENOBUFS);
goto ERROR;
}
break;
#endif
default:
SMSC_ERROR(("smsc_socket: unsupported type = %d",type));
set_errno(EINVAL);
goto ERROR;
}
set_errno(0);
return socketIndex;
ERROR:
if(socketIndex>=0) {
free_socket(socketIndex);
socketIndex=-1;
}
return -1;
}
int smsc_accept(int socketIndex, struct sockaddr * addr, socklen_t * addrlen)
{
#if TCP_ENABLED
int newSocketIndex=-1;
struct SOCKET * newSocket=NULL;
struct SOCKET * socket=NULL;
IP_ADDRESS ipAddress;
u16_t port;
socket=get_socket(socketIndex);
newSocketIndex=alloc_socket();
if (newSocketIndex == -1) {
set_errno(ENOBUFS);
goto ERROR;
}
newSocket=get_socket(newSocketIndex);
/* only TCP sockets can use the accept call */
SMSC_ASSERT(socket->mType==SOCKET_TYPE_TCP);
if(SocketRequest_AcceptTcpControlBlock(socket,newSocket,&ipAddress,&port)!=0) {
SMSC_ERROR(("smsc_accept: failed to accept tcp control block"));
set_errno(ENOBUFS);
goto ERROR;
}
if((addr!=NULL)&&(addrlen!=NULL)&&((*addrlen)>=sizeof(struct sockaddr_in)))
{
SMSC_ASSERT(IP_ADDRESS_IS_IPV4(&ipAddress));
((struct sockaddr_in *)addr)->sin_len=sizeof(struct sockaddr_in);
((struct sockaddr_in *)addr)->sin_family=AF_INET;
IPV4_ADDRESS_COPY_FROM_IP_ADDRESS(&(((struct sockaddr_in *)addr)->sin_addr.s_addr),&ipAddress);
((struct sockaddr_in *)addr)->sin_port=ntohs(port);
}
set_errno(0);
return newSocketIndex;
ERROR:
if(newSocketIndex>=0) {
free_socket(newSocketIndex);
newSocketIndex=-1;
}
#endif /* TCP_ENABLED */
return -1;
}
int smsc_bind(int socketIndex, struct sockaddr *name, socklen_t namelen)
{
struct SOCKET * socket;
IP_ADDRESS local_addr;
u16_t local_port;
err_t error;
socket = get_socket(socketIndex);
if (!socket) {
set_errno(EBADF);
return -1;
}
SMSC_ASSERT(name->sa_family==AF_INET);
IP_ADDRESS_COPY_FROM_IPV4_ADDRESS(&local_addr,&(((struct sockaddr_in *)name)->sin_addr.s_addr));
local_port = ((struct sockaddr_in *)name)->sin_port;
#if SMSC_TRACE_ENABLED
{
char addressString[IP_ADDRESS_STRING_SIZE];
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_bind(%d, addr=%s port=%u)",
socketIndex,IP_ADDRESS_TO_STRING(addressString,&local_addr),
ntohs(local_port)));
}
#endif
error = SocketRequest_Bind(socket, &local_addr, ntohs(local_port));
if (error != ERR_OK) {
SMSC_WARNING(SOCKETS_DEBUG, ("smsc_bind(%d) failed, error=%d", socketIndex, error));
sock_set_errno(socket, err_to_errno(error));
return -1;
}
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_bind(%d) succeeded", socketIndex));
sock_set_errno(socket, 0);
return 0;
}
int smsc_close(int s)
{
struct SOCKET * socket;
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_close(%d)", s));
/* We cannot allow multiple closes of the same socket. */
smsc_semaphore_wait(&gSocketsLock);
socket = get_socket(s);
if (!socket) {
smsc_semaphore_signal(&gSocketsLock);
set_errno(EBADF);
return -1;
}
SocketRequest_Close(socket);
ASSIGN_SIGNATURE(socket,0);
socket->mIsActive=0;
smsc_semaphore_signal(&gSocketsLock);
sock_set_errno(socket, 0);
return 0;
}
int smsc_connect(int s, struct sockaddr *name, socklen_t namelen)
{
struct SOCKET *socket;
err_t err;
socket = get_socket(s);
if (!socket) {
set_errno(EBADF);
return -1;
}
if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
SMSC_NOTICE(SOCKETS_DEBUG, ("smsc_connect(%d, AF_UNSPEC)", s));
err = SocketRequest_Disconnect(socket);
} else {
IP_ADDRESS remote_addr;
u16_t remote_port;
SMSC_ASSERT(name->sa_family==AF_INET);/* only Ipv4 is currently supported */
IP_ADDRESS_COPY_FROM_IPV4_ADDRESS(&remote_addr,&(((struct sockaddr_in *)name)->sin_addr.s_addr));
remote_port = ((struct sockaddr_in *)name)->sin_port;
#if SMSC_TRACE_ENABLED
{
char addressString[IP_ADDRESS_STRING_SIZE];
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_connect(%d, addr=%s port=%u)", s,
IP_ADDRESS_TO_STRING(addressString,&remote_addr),ntohs(remote_port)));
}
#endif
err= SocketRequest_Connect(socket, &remote_addr, ntohs(remote_port));
}
if (err != ERR_OK) {
SMSC_NOTICE(SOCKETS_DEBUG, ("smsc_connect(%d) failed, err=%d", s, err));
sock_set_errno(socket, err_to_errno(err));
return -1;
}
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_connect(%d) succeeded", s));
sock_set_errno(socket, 0);
return 0;
}
int smsc_listen(int s, int backlog)
{
#if TCP_ENABLED
struct SOCKET * socket;
err_t err;
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_listen(%d, backlog=%d)", s, backlog));
socket = get_socket(s);
if (!socket) {
set_errno(EBADF);
return -1;
}
if(backlog>SOCKET_MAXIMUM_BACKLOG) {
set_errno(EINVAL);
return -1;
}
socket->mListenBackLog=backlog;
err=SocketRequest_Listen(socket);
if(err!=ERR_OK) {
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_listen(%d) failed, err=%d", s, err));
sock_set_errno(socket, err_to_errno(err));
return -1;
}
sock_set_errno(socket, 0);
return 0;
#else
set_errno(EINVAL);
return -1;
#endif
}
int smsc_recvfrom(int s, void *mem, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen)
{
struct SOCKET *socket;
int result=-1;
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_recvfrom(%d, %p, %d, 0x%x, ..)", s, mem, len, flags));
socket = get_socket(s);
if (!socket) {
set_errno(EBADF);
return -1;
}
/* If this is non-blocking call, then check first */
if (((flags & MSG_DONTWAIT) || (socket->mFlags & O_NONBLOCK))
&& ((!(SocketPacketQueue_IsEmpty(&(socket->mReceiveQueue))))||(socket->mReceiveFinishedFlag)) )
{
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_recvfrom(%d): returning EWOULDBLOCK", s));
sock_set_errno(socket, EWOULDBLOCK);
return -1;
}
{
IP_ADDRESS ipAddress;
u16_t port;
result=SocketRequest_Receive(socket,mem,len,&ipAddress,&port);
#if SMSC_TRACE_ENABLED
{
char addressString[IP_ADDRESS_STRING_SIZE];
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_recvfrom(%d): addr=%s port=%u, size=%d", s,
IP_ADDRESS_TO_STRING(addressString,&ipAddress),port,result));
}
#endif
if (from && fromlen) {
struct sockaddr_in sin;
SMSC_ASSERT(IP_ADDRESS_IS_IPV4(&ipAddress));
memset(&sin, 0, sizeof(sin));
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
IPV4_ADDRESS_COPY_FROM_IP_ADDRESS(
&(sin.sin_addr.s_addr),&ipAddress);
if (*fromlen > sizeof(sin))
*fromlen = sizeof(sin);
memcpy(from, &sin, *fromlen);
}
}
if(result>=0) {
sock_set_errno(socket, 0);
} else {
sock_set_errno(socket, ECONNRESET);
}
return result;
}
int smsc_recv(int s, void *mem, int len, unsigned int flags)
{
return smsc_recvfrom(s, mem, len, flags, NULL, NULL);
}
int smsc_send(int s, void *data, int size, unsigned int flags)
{
struct SOCKET * socket;
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_send(%d, data=%p, size=%d, flags=0x%x)", s, data, size, flags));
socket = get_socket(s);
if (!socket) {
set_errno(EBADF);
return -1;
}
size=SocketRequest_Send(socket,data,size,flags);
if(size<0) {
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_send(%d) err=%d", s, size));
set_errno(-size);
return -1;
}
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_send(%d) ok size=%d", s, size));
sock_set_errno(socket, 0);
return size;
}
int smsc_sendto(int s, void *data, int size, unsigned int flags,
struct sockaddr *to, socklen_t tolen)
{
struct SOCKET * socket;
IP_ADDRESS remote_addr, addr;
u16_t remote_port, port;
int ret,connected;
socket = get_socket(s);
if (!socket) {
set_errno(EBADF);
return -1;
}
/* get the peer if currently connected */
connected = (SocketRequest_GetPeer(socket, &addr, &port) == ERR_OK);
SMSC_ASSERT(to!=NULL);
SMSC_ASSERT(to->sa_family==AF_INET);/* Only Ipv4 is suppored currently */
IP_ADDRESS_COPY_FROM_IPV4_ADDRESS(&remote_addr,&((struct sockaddr_in *)to)->sin_addr.s_addr);
remote_port = ((struct sockaddr_in *)to)->sin_port;
#if SMSC_TRACE_ENABLED
{
char addressString[IP_ADDRESS_STRING_SIZE];
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_sendto(%d, data=%p, size=%d, flags=0x%x to=%s port=%u", s, data, size, flags,
IP_ADDRESS_TO_STRING(addressString,&remote_addr),ntohs(remote_port)));
}
#endif
SocketRequest_Connect(socket, &remote_addr, ntohs(remote_port));
ret = smsc_send(s, data, size, flags);
/* reset the remote address and port number
of the connection */
if (connected)
SocketRequest_Connect(socket, &addr, port);
else
SocketRequest_Disconnect(socket);
return ret;
}
static int smsc_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
{
int i, nready = 0;
fd_set lreadset, lwriteset, lexceptset;
struct SOCKET *p_sock;
FD_ZERO(&lreadset);
FD_ZERO(&lwriteset);
FD_ZERO(&lexceptset);
/* Go through each socket in each list to count number of sockets which
currently match */
for(i = 0; i < maxfdp1; i++)
{
if (FD_ISSET(i, readset))
{
/* See if netconn of this socket is ready for read */
p_sock = get_socket(i);
if (p_sock && (!SocketPacketQueue_IsEmpty(&(p_sock->mReceiveQueue))))
{
FD_SET(i, &lreadset);
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_selscan: fd=%d ready for reading", i));
nready++;
}
}
if (FD_ISSET(i, writeset))
{
/* See if netconn of this socket is ready for write */
p_sock = get_socket(i);
if (p_sock && (p_sock->mIsWritable))
{
FD_SET(i, &lwriteset);
SMSC_TRACE(SOCKETS_DEBUG, ("smsc_selscan: fd=%d ready for writing", i));
nready++;
}
}
}
*readset = lreadset;
*writeset = lwriteset;
FD_ZERO(exceptset);
return nready;
}
int smsc_select(
int maxfdp1,
fd_set *readset,
fd_set *writeset,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -