⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockets.c

📁 由smsc公司改进的lwip2.1.1基于嵌入式系统的TCP/ip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
		#if UDP_ENABLED
		if(isUdp) {
			IP_ADDRESS_COPY(&(socket->mRequestParameters.mReceiveParams.mIpAddress),&originalSourceAddress);
			socket->mRequestParameters.mReceiveParams.mPort=originalSourcePort;
		} else 
		#endif
		{
			#if TCP_ENABLED
			SMSC_ASSERT(socket->mControlBlock.mTcp!=NULL);
			Tcp_AcknowledgeReceivedData(
				socket->mControlBlock.mTcp,
				socket->mRequestParameters.mReceiveParams.mSize);
			IP_ADDRESS_COPY(&(socket->mRequestParameters.mReceiveParams.mIpAddress),
				Tcp_GetRemoteAddress(socket->mControlBlock.mTcp));
			socket->mRequestParameters.mReceiveParams.mPort=
				Tcp_GetRemotePort(socket->mControlBlock.mTcp);
			#endif /* TCP_ENABLED */
		}
	} else 
#endif /* UDP_ENABLED||TCP_ENABLED */
	{
		SMSC_ERROR(("SocketsInternal_DoReceiveCopy: Unexpected socket type"));
	}
}

#if UDP_ENABLED
static void SocketsInternal_UdpReceiveFunction(void * param,
	struct UDP_CONTROL_BLOCK * udpControlBlock,
	struct PACKET_BUFFER * packetBuffer,
	PIP_ADDRESS sourceAddress,
	u16_t sourcePort)
{
	struct SOCKET * socket=(struct SOCKET *)param;
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	
	SMSC_ASSERT(packetBuffer!=NULL);
	SMSC_ASSERT(sourceAddress!=NULL);
	
	SocketsInternal_PrependSocketData(packetBuffer,sourceAddress,sourcePort);
	
	SocketPacketQueue_Push(&(socket->mReceiveQueue),packetBuffer);
	
	if((socket->mResponseCode==RESPONSE_PENDING)&&
		(socket->mRequestCode==REQUEST_RECEIVE))
	{
		SocketsInternal_DoReceiveCopy(socket);
		socket->mResponseCode=RESPONSE_SUCCESSFUL;
		smsc_semaphore_signal(&(socket->mResponseSignal));
	}
}
#endif /* UDP_ENABLED */

#if UDP_ENABLED
static void SocketsInternal_DoCreateUdpControlBlock(struct SOCKET * socket)
{
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	if(socket->mType!=SOCKET_TYPE_UNDEFINED) {
		SocketsInternal_FreeControlBlock(socket);
		SMSC_ASSERT(socket->mType==SOCKET_TYPE_UNDEFINED);
	}
	SMSC_ASSERT(socket->mControlBlock.mUdp==NULL);
	socket->mControlBlock.mUdp=Udp_CreateControlBlock();
	if(socket->mControlBlock.mUdp!=NULL) {
		socket->mType=SOCKET_TYPE_UDP;
		if(socket->mRequestParameters.mCreateUdpParams.mUseUdpLite) {
			Udp_SetFlags(socket->mControlBlock.mUdp,UDP_FLAGS_UDPLITE);
		}
		Udp_SetReceiverCallBack(
			socket->mControlBlock.mUdp,
			SocketsInternal_UdpReceiveFunction,(void *)socket);
		socket->mResponseCode=RESPONSE_SUCCESSFUL;
	} else {
		socket->mResponseCode=RESPONSE_MEMORY_ERROR;
	}
}
#endif /* UDP_ENABLED */

static void SocketsInternal_SignalWaitingThreads(struct SOCKET * socket)
{
	struct smsc_select_cb * scb;
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	while (1)
	{
		smsc_semaphore_wait(&gSelectLock);
		for (scb = gSelectList; scb; scb = scb->next)
		{
			if (scb->sem_signalled == 0)
			{
				/* Test this select call for our socket */
				if (scb->readset && FD_ISSET(socket->mSocketIndex, scb->readset))
					if ((!SocketPacketQueue_IsEmpty(&(socket->mReceiveQueue)))||
						(socket->mReceiveFinishedFlag)
						#if TCP_ENABLED
						||(socket->mAcceptListSize>0)
						||(socket->mConnectionWasReset)
						#endif
						)
						break;
				if (scb->writeset && FD_ISSET(socket->mSocketIndex, scb->writeset))
					if ((socket->mIsWritable)
						#if TCP_ENABLED
						||(socket->mConnectionWasReset)
						#endif
						)
						break;
			}
		}
		if (scb)
		{
			scb->sem_signalled = 1;
			smsc_semaphore_signal(&gSelectLock);
			smsc_semaphore_signal(scb->sem);
		} else {
			smsc_semaphore_signal(&gSelectLock);
			break;
		}
	}
}

#if TCP_ENABLED
/* Function to be called when more send buffer space is available. */
static err_t SocketsInternal_TcpSentCallBack(void *arg, struct TCP_CONTROL_BLOCK * tcpControlBlock, u16_t space)
{
	struct SOCKET * socket=(struct SOCKET *)arg;
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	
	SMSC_ASSERT(socket->mType==SOCKET_TYPE_TCP);
	if(Tcp_GetAvailableSendSpace(socket->mControlBlock.mTcp)>TCP_SENDABLE_THRESHOLD) {
		socket->mIsWritable=1;
		SocketsInternal_SignalWaitingThreads(socket);
	}
	return ERR_OK;
}

/* Function to be called when (in-sequence) data has arrived. */
static err_t SocketsInternal_TcpReceiveCallBack(void *arg, struct TCP_CONTROL_BLOCK * tcpControlBlock, struct PACKET_BUFFER * packetBuffer, err_t err)
{
	struct SOCKET * socket=(struct SOCKET *)arg;
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	SMSC_TRACE(SOCKETS_DEBUG,("SocketsInternal_TcpReceiveCallBack:"));
	if(packetBuffer!=NULL) {
		/* we should not receive more data after receiving end of data */
		SMSC_ASSERT(socket->mReceiveFinishedFlag==0);
		while(packetBuffer!=NULL) {
			struct PACKET_BUFFER * next=PacketBuffer_GetSetNext(packetBuffer,NULL);
			SocketPacketQueue_Push(&(socket->mReceiveQueue),packetBuffer);
			packetBuffer=next;
		}
	} else {
		socket->mReceiveFinishedFlag=1;
	}

	if((socket->mResponseCode==RESPONSE_PENDING)&&
		(socket->mRequestCode==REQUEST_RECEIVE))
	{
		SocketsInternal_DoReceiveCopy(socket);
		socket->mResponseCode=RESPONSE_SUCCESSFUL;
		smsc_semaphore_signal(&(socket->mResponseSignal));
	}
	
	if((!SocketPacketQueue_IsEmpty(&(socket->mReceiveQueue)))||
		(socket->mReceiveFinishedFlag))
	{
		SocketsInternal_SignalWaitingThreads(socket);
	}
	return ERR_OK;
}

/* called to queue the packets when the new control block is not yet associated to new socket. */
static err_t SocketsInternal_PreTcpReceiveCallBack(void *arg, struct TCP_CONTROL_BLOCK * tcpControlBlock, struct PACKET_BUFFER * packetBuffer, err_t err)
{
	struct PACKET_BUFFER * tmpbuf=(struct PACKET_BUFFER *)arg;
	SMSC_TRACE(SOCKETS_DEBUG,("SocketsInternal_PreTcpReceiveCallBack:"));
	
	/* link the packetBuffers and hold it through tcpControlBlock->mCallbackArgument */
	if (tmpbuf!=NULL) {
		/* chain it up */
		while(PacketBuffer_GetNext(tmpbuf) != NULL)
			tmpbuf=PacketBuffer_GetNext(tmpbuf);
		PacketBuffer_SetNext(tmpbuf,packetBuffer);
	} else {
		Tcp_SetCallBackArgument(tcpControlBlock,packetBuffer);		
	}
	return ERR_OK;
}
/* Function to be called when a connection has been set up. */
static err_t SocketsInternal_TcpConnectedCallBack(void *arg, struct TCP_CONTROL_BLOCK * tcpControlBlock, err_t err)
{
	struct SOCKET * socket=(struct SOCKET *)arg;
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	SMSC_ASSERT(socket->mType==SOCKET_TYPE_TCP);
	SMSC_ASSERT(socket->mRequestCode==REQUEST_CONNECT);
	SMSC_ASSERT(socket->mResponseCode==RESPONSE_PENDING);
	
	socket->mErrorCode=err;
	if(err==ERR_OK) {
		socket->mResponseCode=RESPONSE_SUCCESSFUL;
	} else {
		socket->mResponseCode=RESPONSE_UNSUCCESSFUL;
	}
	smsc_semaphore_signal(&(socket->mResponseSignal));
	return ERR_OK;
}

static void SocketsInternal_AcceptNewTcpControlBlock(
	struct SOCKET * socket);

/* Function to call when a listener has been connected. */
static err_t SocketsInternal_TcpAcceptCallBack(void *arg, struct TCP_CONTROL_BLOCK * newControlBlock, err_t err)
{
	struct SOCKET * socket=(struct SOCKET *)arg;
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	SMSC_ASSERT(newControlBlock!=NULL);
	
	if(socket->mAcceptListSize<socket->mListenBackLog) {
		SMSC_ASSERT(socket->mAcceptListSize<SOCKET_MAXIMUM_BACKLOG);
		
		/*Tcp_SetCallBackArgument(socket->mRequestParameters.mAcceptParams.mNewSocket->mControlBlock.mTcp,
			socket->mRequestParameters.mAcceptParams.mNewSocket);
	
	Tcp_SetErrorCallBack(socket->mRequestParameters.mAcceptParams.mNewSocket->mControlBlock.mTcp,SocketsInternal_TcpErrorCallBack);
	Tcp_SetReceiveCallBack(socket->mRequestParameters.mAcceptParams.mNewSocket->mControlBlock.mTcp,SocketsInternal_TcpReceiveCallBack);
	Tcp_SetSentCallBack(socket->mRequestParameters.mAcceptParams.mNewSocket->mControlBlock.mTcp,SocketsInternal_TcpSentCallBack);
        */
        /* Initialize temporary receive callback, to receive packets when the application not yet called accept() */
        Tcp_SetReceiveCallBack(newControlBlock,SocketsInternal_PreTcpReceiveCallBack);
        Tcp_SetCallBackArgument(newControlBlock,NULL);
        
		socket->mAcceptList[socket->mAcceptListSize]=newControlBlock;
		socket->mAcceptListSize++;
				
		if((socket->mResponseCode==RESPONSE_PENDING)&&
			(socket->mRequestCode==REQUEST_ACCEPT)) 
		{
			SocketsInternal_AcceptNewTcpControlBlock(socket);
			smsc_semaphore_signal(&(socket->mResponseSignal));
		}
		if(socket->mAcceptListSize>0) {
			SocketsInternal_SignalWaitingThreads(socket);
		}
	} else {
		SMSC_NOTICE(SOCKETS_DEBUG,("SocketsInternal_TcpAcceptCallBack: Unable to accept connection"));
		SMSC_NOTICE(SOCKETS_DEBUG,("    Too many connection on backlog"));
		return ERR_ABRT;
	}

	return ERR_OK;
}

/* Function to be called whenever a fatal error occurs. */
static void SocketsInternal_TcpErrorCallBack(void *arg, err_t err)
{
	struct SOCKET * socket=(struct SOCKET *)arg;

	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	SMSC_ASSERT(socket->mType==SOCKET_TYPE_TCP);

	if(err==ERR_RST) {
		SMSC_NOTICE(SOCKETS_DEBUG,("SocketsInternal_TcpErrorCallBack: RESET detected"));
		socket->mConnectionWasReset=1;
		if(socket->mResponseCode==RESPONSE_PENDING) {
			if(socket->mRequestCode==REQUEST_RECEIVE) {
				SocketsInternal_DoReceiveCopy(socket);
				socket->mResponseCode=RESPONSE_CONNECTION_RESET;
				smsc_semaphore_signal(&(socket->mResponseSignal));
			}
		}
		SocketsInternal_SignalWaitingThreads(socket);
	} else {
		SMSC_WARNING(SOCKETS_DEBUG,("SocketsInternal_TcpErrorCallBack: Unhandled error, err=%d",err));
	}
}

static void SocketsInternal_DoCreateTcpControlBlock(struct SOCKET * socket)
{
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	if(socket->mType!=SOCKET_TYPE_UNDEFINED) {
		SocketsInternal_FreeControlBlock(socket);
		SMSC_ASSERT(socket->mType==SOCKET_TYPE_UNDEFINED);
	}
	SMSC_ASSERT(socket->mControlBlock.mTcp==NULL);
	socket->mControlBlock.mTcp=Tcp_NewControlBlock();
	if(socket->mControlBlock.mTcp!=NULL) {
		socket->mType=SOCKET_TYPE_TCP;
		Tcp_SetCallBackArgument(socket->mControlBlock.mTcp,socket);
		Tcp_SetErrorCallBack(socket->mControlBlock.mTcp,SocketsInternal_TcpErrorCallBack);
		Tcp_SetReceiveCallBack(socket->mControlBlock.mTcp,SocketsInternal_TcpReceiveCallBack);
		Tcp_SetSentCallBack(socket->mControlBlock.mTcp,SocketsInternal_TcpSentCallBack);
		socket->mResponseCode=RESPONSE_SUCCESSFUL;
	} else {
		socket->mResponseCode=RESPONSE_MEMORY_ERROR;
	}
}
#endif /* TCP_ENABLED */

static void SocketsInternal_DoBind(struct SOCKET * socket)
{
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	if (socket->mControlBlock.mPointer == NULL) {
		/* Need to create a control block first
			in other words smsc_socket must complete successfully */
		SMSC_WARNING(SOCKETS_DEBUG,("SocketsInternal_DoBind: Illegal Operation"));
		socket->mResponseCode=RESPONSE_ILLEGAL_OPERATION;
		return;
	}
	switch (socket->mType) {
#if RAW_ENABLED
	case SOCKET_TYPE_RAW:
		/*msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);*/
		SMSC_ERROR(("SocketsInternal_DoBind: Raw sockets not implemented"));
		break;
#endif
#if UDP_ENABLED
	case SOCKET_TYPE_UDP:
		if(Udp_Bind(
			socket->mControlBlock.mUdp,
			&(socket->mRequestParameters.mBindParams.mIpAddress), 
			socket->mRequestParameters.mBindParams.mPort)==ERR_OK)
		{
			socket->mResponseCode=RESPONSE_SUCCESSFUL;
		} else {
			socket->mResponseCode=RESPONSE_UNSUCCESSFUL;
		}
		break;
#endif
#if TCP_ENABLED
	case SOCKET_TYPE_TCP:
		if(Tcp_Bind(socket->mControlBlock.mTcp,
			&(socket->mRequestParameters.mBindParams.mIpAddress),
			socket->mRequestParameters.mBindParams.mPort)==ERR_OK) 
		{
			socket->mResponseCode=RESPONSE_SUCCESSFUL;
		} else {
			socket->mResponseCode=RESPONSE_UNSUCCESSFUL;
		}
		break;
#endif
	default:
		SMSC_WARNING(SOCKETS_DEBUG,("SocketsInternal_DoBind: Unknown Socket Type=%"U16_F,(u16_t)(socket->mType)));
		socket->mResponseCode=RESPONSE_ILLEGAL_OPERATION;
		break;
	}
}

static void SocketsInternal_DoConnect(struct SOCKET * socket)
{
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	if (socket->mControlBlock.mPointer == NULL) {
		/* Need to create a control block first
			in other words smsc_socket must complete successfully */
		SMSC_WARNING(SOCKETS_DEBUG,("SocketsInternal_DoConnect: Illegal Operation"));
		socket->mResponseCode=RESPONSE_ILLEGAL_OPERATION;
		return;
	}
	switch (socket->mType) {
#if RAW_ENABLED
	case SOCKET_TYPE_RAW:
		/*raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);*/
		SMSC_ERROR(("SocketsInternal_DoConnect: Raw sockets not implemented"));
		socket->mResponseCode=RESPONSE_ILLEGAL_OPERATION;
		break;
#endif
#if UDP_ENABLED
	case SOCKET_TYPE_UDP:
		if(Udp_Connect(socket->mControlBlock.mUdp,
			&(socket->mRequestParameters.mConnectParams.mIpAddress),
			socket->mRequestParameters.mConnectParams.mPort)==ERR_OK)
		{
			socket->mResponseCode=RESPONSE_SUCCESSFUL;
		} else {
			socket->mResponseCode=RESPONSE_UNSUCCESSFUL;
		}
		break;
#endif
#if TCP_ENABLED
	case SOCKET_TYPE_TCP:
		Tcp_Connect(socket->mControlBlock.mTcp,
			&(socket->mRequestParameters.mConnectParams.mIpAddress),
			socket->mRequestParameters.mConnectParams.mPort,
			SocketsInternal_TcpConnectedCallBack);
		socket->mReceiveFinishedFlag=0;
		socket->mResponseCode=RESPONSE_PENDING;
		break;
#endif
	default:
		SMSC_WARNING(SOCKETS_DEBUG,("SocketsInternal_DoConnect: Unknown Socket Type=%"U16_F,(u16_t)(socket->mType)));
		socket->mResponseCode=RESPONSE_ILLEGAL_OPERATION;
		break;
	}
}

static void SocketsInternal_DoDisconnect(struct SOCKET * socket)
{
	SMSC_ASSERT(socket!=NULL);
	CHECK_SIGNATURE(socket,SOCKET_SIGNATURE);
	socket->mResponseCode=RESPONSE_SUCCESSFUL;
	if (socket->mControlBlock.mPointer == NULL) {
		/* Need to create a control block first
			in other words smsc_socket must complete successfully */
		SMSC_WARNING(SOCKETS_DEBUG,("SocketsInternal_DoDisconnect: Illegal Operation"));
		socket->mResponseCode=RESPONSE_ILLEGAL_OPERATION;
		return;
	}
	switch (socket->mType) {
#if RAW_ENABLED
	case SOCKET_TYPE_RAW:
		/*raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);*/
		SMSC_NOTICE(SOCKETS_DEBUG,("SocketsInternal_DoDisconnect: Raw sockets need not disconnect"));
		break;
#endif
#if UDP_ENABLED
	case SOCKET_TYPE_UDP:
		Udp_Disconnect(socket->mControlBlock.mUdp);
		break;
#endif
#if TCP_ENABLED
	case SOCKET_TYPE_TCP:
		SMSC_NOTICE(SOCKETS_DEBUG,("SocketsInternal_DoDisconnect: TCP sockets need not disconnect, close instead"));
		break;
#endif
	default:
		SMSC_WARNING(SOCKETS_DEBUG,("SocketsInternal_DoDisconnect: Unknown Socket Type=%"U16_F,(u16_t)(socket->mType)));
		socket->mResponseCode=R

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -