📄 sockets.c
字号:
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
* Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
*
*/
/*
Modifications of this software Copyright(C) 2008, Standard Microsystems Corporation
All Rights Reserved.
The modifications to this program code are proprietary to SMSC and may not be copied,
distributed, or used without a license to do so. Such license may have
Limited or Restricted Rights. Please refer to the license for further
clarification.
*/
#include "core/sps.h"
#include "smsc_threading.h"
#include "api/sockets.h"
#include "api/utilities.h"
#if !SOCKETS_ENABLED
#error Sockets are not enabled
#endif
#if !SMSC_THREADING_ENABLED
#error Multithreading is not enabled
#endif
static int err_to_errno_table[11] = {
0, /* ERR_OK 0 No error, everything OK. */
ENOMEM, /* ERR_MEM -1 Out of memory error. */
ENOBUFS, /* ERR_BUF -2 Buffer error. */
ECONNABORTED, /* ERR_ABRT -3 Connection aborted. */
ECONNRESET, /* ERR_RST -4 Connection reset. */
ESHUTDOWN, /* ERR_CLSD -5 Connection closed. */
ENOTCONN, /* ERR_CONN -6 Not connected. */
EINVAL, /* ERR_VAL -7 Illegal value. */
EIO, /* ERR_ARG -8 Illegal argument. */
EHOSTUNREACH, /* ERR_RTE -9 Routing problem. */
EADDRINUSE /* ERR_USE -10 Address in use. */
};
#define ERR_TO_ERRNO_TABLE_SIZE \
(sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
#define err_to_errno(err) \
(-(err) >= 0 && -(err) < ERR_TO_ERRNO_TABLE_SIZE ? \
err_to_errno_table[-(err)] : EIO)
#define set_errno(err) errno = (err)
#define sock_set_errno(socket, errorCode) do { \
(socket)->mErrorCode = (errorCode); \
set_errno((socket)->mErrorCode); \
} while (0)
#define SOCKET_PACKET_QUEUE_SIGNATURE (0x4DB72711)
/*****************************************************************************
* STRUCTURE: SOCKET_PACKET_QUEUE
* Used to maintain packet queue context.
* Should not access this structure directly.
* Should use PacketQueue_ function for all accesses
*****************************************************************************/
struct SOCKET_PACKET_QUEUE {
DECLARE_SIGNATURE /* used for run time type checking and memory corruption detection */
struct PACKET_BUFFER * mHead;
struct PACKET_BUFFER * mTail;
};
#define SOCKET_SIGNATURE (0x9E3ECFF5)
struct SOCKET
{
DECLARE_SIGNATURE
struct SOCKET * mNext;
u8_t mIsActive;
#define SOCKET_TYPE_UNDEFINED (0)
u8_t mType;
union {
void * mPointer;
#if RAW_ENABLED
#define SOCKET_TYPE_RAW (1)
/*struct raw_pcb *raw;*/
#endif
#if UDP_ENABLED
#define SOCKET_TYPE_UDP (2)
struct UDP_CONTROL_BLOCK *mUdp;
#endif
#if TCP_ENABLED
#define SOCKET_TYPE_TCP (3)
struct TCP_CONTROL_BLOCK *mTcp;
#endif
} mControlBlock;
SMSC_SEMAPHORE mRequestLock;
SMSC_SEMAPHORE mResponseSignal;
#define REQUEST_UNDEFINED (0)
#if UDP_ENABLED
#define REQUEST_CREATE_UDP_CONTROL_BLOCK (1)
#endif
#if TCP_ENABLED
#define REQUEST_CREATE_TCP_CONTROL_BLOCK (2)
#endif
#define REQUEST_BIND (3)
#define REQUEST_CONNECT (4)
#define REQUEST_DISCONNECT (5)
#define REQUEST_SEND (6)
#define REQUEST_RECEIVE (7)
#define REQUEST_CLOSE (8)
#define REQUEST_LISTEN (9)
#define REQUEST_ACCEPT (10)
u8_t mRequestCode;
#define RESPONSE_UNDEFINED (0)
#define RESPONSE_SUCCESSFUL (1)
#define RESPONSE_UNSUCCESSFUL (2)
#define RESPONSE_MEMORY_ERROR (3)
#define RESPONSE_UNKNOWN_REQUEST (4)
#define RESPONSE_ILLEGAL_OPERATION (5)
#define RESPONSE_PENDING (6)
#define RESPONSE_CONNECTION_RESET (7)
u8_t mResponseCode;
union {
#if UDP_ENABLED
struct {
u8_t mUseUdpLite;
} mCreateUdpParams;
#endif
struct {
IP_ADDRESS mIpAddress;
u16_t mPort;
} mBindParams;
struct {
IP_ADDRESS mIpAddress;
u16_t mPort;
} mConnectParams;
struct {
void * mData;
int mSize;
unsigned int mFlags;
} mSendParams;
struct {
void * mData;
int mSize;
IP_ADDRESS mIpAddress;
u16_t mPort;
} mReceiveParams;
struct {
struct SOCKET * mNewSocket;
IP_ADDRESS mFromIpAddress;
u16_t mFromPort;
} mAcceptParams;
} mRequestParameters;
int mErrorCode;
int mSocketIndex;
int mReceiveFinishedFlag;
struct SOCKET_PACKET_QUEUE mReceiveQueue;
#if TCP_ENABLED
int mListenBackLog;
struct TCP_CONTROL_BLOCK * mAcceptList[SOCKET_MAXIMUM_BACKLOG];
u8_t mAcceptListSize;
int mConnectionWasReset;
#endif
int mIsWritable;
u16_t mFlags;
};
struct smsc_select_cb
{
struct smsc_select_cb *next;
fd_set *readset;
fd_set *writeset;
fd_set *exceptset;
int sem_signalled;
PSMSC_SEMAPHORE sem;
};
static struct SOCKET sockets[MAXIMUM_NUMBER_OF_SOCKETS];
static SMSC_SEMAPHORE gSocketsLock;
static struct smsc_select_cb * gSelectList = NULL;
static struct SOCKET * gRequestQueueHead=NULL;
static struct SOCKET * gRequestQueueTail=NULL;
static SMSC_SEMAPHORE gRequestQueueLock;
static SMSC_SEMAPHORE gSelectLock;
static void SocketsInternal_RequestHandler(void * param);
static struct TASK *gSocketTask=NULL;
static void Sockets_PushRequest(struct SOCKET * socket);
static struct SOCKET * Sockets_PopRequest(void);
#if UDP_ENABLED
static int SocketRequest_CreateUdpControlBlock(struct SOCKET * socket);
#endif
#if TCP_ENABLED
static int SocketRequest_CreateTcpControlBlock(struct SOCKET * socket);
#endif
static int SocketRequest_Bind(struct SOCKET * socket, PIP_ADDRESS ipAddress, u16_t port);
static err_t SocketRequest_Connect(struct SOCKET * socket, PIP_ADDRESS ipAddress, u16_t port);
static err_t SocketRequest_Disconnect(struct SOCKET * socket);
static err_t SocketRequest_GetPeer(struct SOCKET * socket,PIP_ADDRESS ipAddress, u16_t * port);
static int SocketRequest_Send(struct SOCKET * socket, void *data, int size, unsigned int flags);
static int SocketRequest_Receive(
struct SOCKET * socket,
void * data,
int size,
PIP_ADDRESS ipAddress,
u16_t * port);
static int SocketRequest_Close(
struct SOCKET * socket);
#if TCP_ENABLED
static err_t SocketRequest_Listen(struct SOCKET * socket);
static int SocketRequest_AcceptTcpControlBlock(
struct SOCKET * listenerSocket,
struct SOCKET * acceptedSocket,
PIP_ADDRESS fromIpAddress,
u16_t * fromPort);
#endif
static void SocketPacketQueue_Initialize(struct SOCKET_PACKET_QUEUE * packetQueue)
{
SMSC_ASSERT(packetQueue!=NULL);
ASSIGN_SIGNATURE(packetQueue,SOCKET_PACKET_QUEUE_SIGNATURE);
packetQueue->mHead=NULL;
packetQueue->mTail=NULL;
}
static int SocketPacketQueue_IsEmpty(struct SOCKET_PACKET_QUEUE * packetQueue)
{
SMSC_ASSERT(packetQueue!=NULL);
CHECK_SIGNATURE(packetQueue,SOCKET_PACKET_QUEUE_SIGNATURE);
return (packetQueue->mHead==NULL);
}
static void SocketPacketQueue_Push(struct SOCKET_PACKET_QUEUE * packetQueue,struct PACKET_BUFFER * packet)
{
SMSC_ASSERT(packetQueue!=NULL);
CHECK_SIGNATURE(packetQueue,SOCKET_PACKET_QUEUE_SIGNATURE);
SMSC_ASSERT(packet!=NULL);
#if SMSC_ERROR_ENABLED
{ /* check that packet is a single chain, and not a chain of chains */
struct PACKET_BUFFER * buffer=PacketBuffer_GetTailBuffer(packet);
SMSC_ASSERT(buffer!=NULL);
SMSC_ASSERT(PacketBuffer_GetNextPointer(buffer)==NULL);
}
#endif /* SMSC_ERROR_ENABLED */
if(packetQueue->mHead!=NULL)
{
struct PACKET_BUFFER * tail=PacketBuffer_GetTailBuffer(packetQueue->mTail);
SMSC_ASSERT(tail!=NULL);
SMSC_ASSERT(PacketBuffer_GetNextPointer(tail)==NULL);
PacketBuffer_SetNextPointer(tail,packet);
}
else
{
SMSC_ASSERT(packetQueue->mTail==NULL);
packetQueue->mHead=packet;
}
packetQueue->mTail=packet;
}
void SocketPacketQueue_UnPop(struct SOCKET_PACKET_QUEUE * packetQueue,struct PACKET_BUFFER * packet)
{
struct PACKET_BUFFER * tailOfPacket=NULL;
SMSC_ASSERT(packetQueue!=NULL);
CHECK_SIGNATURE(packetQueue,SOCKET_PACKET_QUEUE_SIGNATURE);
SMSC_ASSERT(packet!=NULL);
/* Get tail Buffer of packet and
check that packet is a single chain, and not a chain of chains */
tailOfPacket=PacketBuffer_GetTailBuffer(packet);
SMSC_ASSERT(tailOfPacket!=NULL);
SMSC_ASSERT(PacketBuffer_GetNextPointer(tailOfPacket)==NULL);
if(packetQueue->mHead!=NULL) {
SMSC_ASSERT(packetQueue->mTail!=NULL);
PacketBuffer_SetNextPointer(tailOfPacket,packetQueue->mHead);
packetQueue->mHead=packet;
} else {
SMSC_ASSERT(packetQueue->mTail==NULL);
packetQueue->mHead=packet;
packetQueue->mTail=packet;
}
}
struct PACKET_BUFFER * SocketPacketQueue_Pop(struct SOCKET_PACKET_QUEUE * packetQueue)
{
struct PACKET_BUFFER * result=NULL;
SMSC_ASSERT(packetQueue!=NULL);
CHECK_SIGNATURE(packetQueue,SOCKET_PACKET_QUEUE_SIGNATURE);
if(packetQueue->mHead!=NULL) {
struct PACKET_BUFFER * tailOfResult;
SMSC_ASSERT(packetQueue->mTail!=NULL);
result=packetQueue->mHead;
tailOfResult=PacketBuffer_GetTailBuffer(result);
SMSC_ASSERT(tailOfResult!=NULL);
packetQueue->mHead=PacketBuffer_GetNextPointer(tailOfResult);
if(packetQueue->mHead==NULL) {
packetQueue->mTail=NULL;
}
PacketBuffer_SetNextPointer(tailOfResult,NULL);
} else {
SMSC_ASSERT(packetQueue->mTail==NULL);
}
return result;
}
void Sockets_Initialize()
{
memset(sockets,0,sizeof(struct SOCKET)*MAXIMUM_NUMBER_OF_SOCKETS);
smsc_semaphore_initialize(&gSocketsLock,1);
gRequestQueueHead=NULL;
gRequestQueueTail=NULL;
smsc_semaphore_initialize(&gRequestQueueLock,1);
smsc_semaphore_initialize(&gSelectLock,1);
gSelectList=NULL;
gSocketTask=Task_Allocate(TASK_PRIORITY_APPLICATION_NORMAL,
SocketsInternal_RequestHandler,NULL);
SMSC_ASSERT(gSocketTask!=NULL);/* if this assert fails, increase TASK_COUNT */
/* set always on activation list flag */
Task_SetAlwaysOnInterruptActivationList(gSocketTask, 1);
TaskManager_ScheduleByInterruptActivation(gSocketTask);
}
static void Sockets_PushRequest(struct SOCKET * socket)
{
SMSC_ASSERT(socket!=NULL);
CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
SMSC_ASSERT(socket->mNext==NULL);
smsc_semaphore_wait(&gRequestQueueLock);
if(gRequestQueueHead!=NULL) {
SMSC_ASSERT(gRequestQueueTail!=NULL);
SMSC_ASSERT(gRequestQueueTail->mNext==NULL);
gRequestQueueTail->mNext=socket;
gRequestQueueTail=socket;
} else {
SMSC_ASSERT(gRequestQueueTail==NULL);
gRequestQueueTail=socket;
gRequestQueueHead=socket;
}
smsc_semaphore_signal(&gRequestQueueLock);
}
static struct SOCKET * Sockets_PopRequest(void)
{
struct SOCKET * result=NULL;
smsc_semaphore_wait(&gRequestQueueLock);
if(gRequestQueueHead!=NULL) {
SMSC_ASSERT(gRequestQueueTail!=NULL);
result=gRequestQueueHead;
gRequestQueueHead=result->mNext;
result->mNext=NULL;
if(gRequestQueueHead==NULL) {
gRequestQueueTail=NULL;
}
} else {
SMSC_ASSERT(gRequestQueueTail==NULL);
}
smsc_semaphore_signal(&gRequestQueueLock);
return result;
}
static int alloc_socket(void)
{
int i;
/* Protect socket array */
smsc_semaphore_wait(&gSocketsLock);
/* allocate a new socket identifier */
for(i = 0; i < MAXIMUM_NUMBER_OF_SOCKETS; ++i) {
if (!sockets[i].mIsActive) {
memset(&sockets[i],0,sizeof(struct SOCKET));
ASSIGN_SIGNATURE(&(sockets[i]),SOCKET_SIGNATURE);
sockets[i].mIsActive=1;
smsc_semaphore_initialize(&(sockets[i].mRequestLock),1);
smsc_semaphore_initialize(&(sockets[i].mResponseSignal),0);
sockets[i].mRequestCode=REQUEST_UNDEFINED;
sockets[i].mResponseCode=RESPONSE_UNDEFINED;
sockets[i].mErrorCode=0;
sockets[i].mSocketIndex=i;
sockets[i].mIsWritable=1;
sockets[i].mReceiveFinishedFlag=0;
SocketPacketQueue_Initialize(&(sockets[i].mReceiveQueue));
smsc_semaphore_signal(&gSocketsLock);
return i;
}
}
smsc_semaphore_signal(&gSocketsLock);
return -1;
}
static void free_socket(int socketIndex)
{
SMSC_ASSERT(socketIndex>=0);
SMSC_ASSERT(socketIndex<MAXIMUM_NUMBER_OF_SOCKETS);
smsc_semaphore_wait(&gSocketsLock);
CHECK_SIGNATURE(&(sockets[socketIndex]),SOCKET_SIGNATURE);
SMSC_ASSERT(sockets[socketIndex].mIsActive);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -