Пример #1
0
/*****************************************************************************
  Function:
	SOCKET accept(SOCKET s, struct sockaddr* addr, int* addrlen)

  Summary:
	This function accepts connection requests queued for a listening socket.

  Description:
	The accept function is used to accept connection requests
	queued for a listening socket. If a connection request is
	pending, accept removes the request from the queue, and a new
	socket is created for the connection. The original listening
	socket remains open and continues to queue new connection
	requests. The socket must be a SOCK_STREAM type socket.

  Precondition:
	listen function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to
	socket. must be bound to a local name and in listening mode.
	addr - Optional pointer to a buffer that receives the address
	of the connecting entity.
	addrlen - Optional pointer to an integer that contains the
	length of the address addr

  Returns:
	If the accept function succeeds, it returns a non-negative
	integer that is a descriptor for the accepted socket.
	Otherwise, the value INVALID_SOCKET is returned.

  Remarks:
	None.
  ***************************************************************************/
SOCKET accept(SOCKET s, struct sockaddr* addr, int* addrlen)
{
	struct BSDSocket *pListenSock;
	SOCKET_INFO *remoteSockInfo;
	struct sockaddr_in *addrRemote;
	unsigned int sockCount;
	TCP_SOCKET hTCP;

	if( s >= BSD_SOCKET_COUNT )
		return INVALID_SOCKET;

	pListenSock = &BSDSocketArray[s]; /* Get the pointer to listening server socket */

	if ( pListenSock->bsdState != SKT_BSD_LISTEN )
		return INVALID_SOCKET;
	if ( pListenSock->SocketType != SOCK_STREAM )
		return INVALID_SOCKET;

	for(sockCount = 0; sockCount < BSD_SOCKET_COUNT; sockCount++)
	{
		if(BSDSocketArray[sockCount].bsdState != SKT_LISTEN)
			continue;

		if(BSDSocketArray[sockCount].localPort != pListenSock->localPort)
			continue;

		hTCP = BSDSocketArray[sockCount].SocketID;
		
		// We don't care about connections and disconnections before we can 
		// process them, so clear the reset flag
		TCPWasReset(hTCP);	
		
		if(TCPIsConnected(hTCP))
		{
			remoteSockInfo = TCPGetRemoteInfo(hTCP);
			if(addr)
			{
				if(addrlen)
				{
					if((unsigned int)*addrlen < sizeof(struct sockaddr_in))
						return INVALID_SOCKET;
					addrRemote = (struct sockaddr_in *)addr;
					addrRemote->sin_addr.S_un.S_addr = remoteSockInfo->remote.IPAddr.Val;
					addrRemote->sin_port = remoteSockInfo->remotePort.Val;
					*addrlen = sizeof(struct sockaddr_in);
				}
			}
			BSDSocketArray[sockCount].remotePort = remoteSockInfo->remotePort.Val;
			BSDSocketArray[sockCount].remoteIP   = remoteSockInfo->remote.IPAddr.Val;
			BSDSocketArray[sockCount].bsdState = SKT_EST;
			return sockCount;
		}
	}

	return INVALID_SOCKET;
}
Пример #2
0
/*****************************************************************************
  Function:
	int listen( SOCKET s, int backlog )

  Summary:
	The listen function sets the specified socket in a listen mode

  Description:
	This function sets the specified socket in a listen
	mode. Calling the listen function indicates that the
	application is ready to accept connection requests arriving
	at a socket of type SOCK_STREAM. The connection request is
	queued (if possible) until accepted with an accept function.
	The backlog parameter defines the maximum number of pending
	connections that may be queued.

  Precondition:
	bind() must have been called on the s socket first.

  Parameters:
	s - Socket identifier returned from a prior socket() call.
	backlog - Maximum number of connection requests that can be queued.  Note 
		that each backlog requires a TCP_PURPOSE_BERKELEY_SERVER type TCP 
		socket to be allocated in the TCPSocketInitializer[] in TCPIPConfig.h.
		Also, ensure that BSD_SOCKET_COUNT (also in TCPIPConfig.h) is greater 
		than the backlog by at least 1 (more if you have other BSD sockets in 
		use).
	
  Returns:
	Returns 0 on success, else return SOCKET_ERROR.

  Remarks:
	None
  ***************************************************************************/
int listen( SOCKET s, int backlog )
{
	struct BSDSocket *ps;
	SOCKET clientSockID;
	unsigned int socketcount;
	unsigned char assigned;

	if( s >= BSD_SOCKET_COUNT )
		return SOCKET_ERROR;

	ps = &BSDSocketArray[s];

	if(ps->SocketType != SOCK_STREAM)
		return SOCKET_ERROR;

	if(ps->bsdState == SKT_BSD_LISTEN)
		backlog = ps->backlog;

	if((ps->bsdState != SKT_BOUND) && (ps->bsdState != SKT_BSD_LISTEN))
		return SOCKET_ERROR;

	while(backlog--)
	{
		assigned = 0;
		for(socketcount = 0; socketcount < BSD_SOCKET_COUNT; socketcount++)
		{
			if(BSDSocketArray[socketcount].bsdState != SKT_CLOSED)
				continue;

			clientSockID = TCPOpen(0, TCP_OPEN_SERVER, ps->localPort, TCP_PURPOSE_BERKELEY_SERVER);
			if(clientSockID == INVALID_SOCKET)
				return SOCKET_ERROR;
				
			// Clear the first reset flag
			TCPWasReset(clientSockID);

			assigned = 1;
			ps->bsdState = SKT_BSD_LISTEN;
			ps->backlog = backlog;

			BSDSocketArray[socketcount].SocketID = clientSockID;
			BSDSocketArray[socketcount].bsdState = SKT_LISTEN;
			BSDSocketArray[socketcount].isServer = TRUE;
			BSDSocketArray[socketcount].localPort = ps->localPort;
			BSDSocketArray[socketcount].SocketType = SOCK_STREAM;
			break;
		}
		if(!assigned)
			return SOCKET_ERROR;
	}
	return 0; //Success
}
Пример #3
0
/*****************************************************************************
  Function:
	static BOOL HandlePossibleTCPDisconnection(SOCKET s)
	
  Summary:
	Internal function that checks for asynchronous TCP connection state 
	changes and resynchs the BSD socket descriptor state to match. 

  Description:
	Internal function that checks for asynchronous TCP connection state 
	changes and resynchs the BSD socket descriptor state to match. 

  Precondition:
	None

  Parameters:
	s - TCP type socket descriptor returned from a previous call to socket.  
	    This socket must be in the SKT_LISTEN, SKT_IN_PROGRESS, SKT_EST, or 
	    SKT_DISCONNECTED states.

  Returns:
	TRUE - Socket is disconnected
	FALSE - Socket is 

  ***************************************************************************/
static BOOL HandlePossibleTCPDisconnection(SOCKET s)
{
	struct BSDSocket *socket;
	BYTE i;
	BOOL bSocketWasReset;

	socket = &BSDSocketArray[s];

	// Nothing to do if disconnection has already been handled
	if(socket->bsdState == SKT_DISCONNECTED)
		return TRUE;	

	// Find out if a disconnect has occurred
	bSocketWasReset = TCPWasReset(socket->SocketID);

	// For server sockets, if the parent listening socket is still open, 
	// then return this socket to the queue for future backlog processing.
	if(socket->isServer)
	{
		for(i = 0; i < sizeof(BSDSocketArray)/sizeof(BSDSocketArray[0]); i++)
		{
			if(BSDSocketArray[i].bsdState != SKT_BSD_LISTEN)
				continue;
			if(BSDSocketArray[i].localPort == socket->localPort)
			{
				// Nothing to do if a disconnect has not occurred
				if(!bSocketWasReset)
					return FALSE;

				// Listener socket is still open, so just return to the 
				// listening state so that the user must call accept() again to 
				// reuse this BSD socket
				socket->bsdState = SKT_LISTEN;
				return TRUE;
			}
		}
	}
			
	// If we get down here and the socket was reset, then this socket 
	// should be closed so that no more clients can connect to it.  However, 
	// we can't go to the BSD SKT_CLOSED state directly since the user still 
	// has to call closesocket() with this s SOCKET descriptor first.
	if(bSocketWasReset)
	{
		TCPClose(socket->SocketID);
		socket->bsdState = SKT_DISCONNECTED;
		return TRUE;
	}
	
	return FALSE;
}
Пример #4
0
/*********************************************************************
 * Function:        void UART2TCPBridgeTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void UART2TCPBridgeTask(void)
{
	static enum _BridgeState
	{
		SM_HOME = 0,
		SM_SOCKET_OBTAINED
	} BridgeState = SM_HOME;
	static TCP_SOCKET MySocket = INVALID_SOCKET;
	WORD wMaxPut, wMaxGet, w;
	BYTE *RXHeadPtrShadow, *RXTailPtrShadow;
	BYTE *TXHeadPtrShadow, *TXTailPtrShadow;


	switch(BridgeState)
	{
		case SM_HOME:
			#if defined(USE_REMOTE_TCP_SERVER)
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
			#else
				MySocket = TCPOpen(0, TCP_OPEN_SERVER, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
			#endif
			
			// Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			// Eat the first TCPWasReset() response so we don't 
			// infinitely create and reset/destroy client mode sockets
			TCPWasReset(MySocket);
			
			// We have a socket now, advance to the next state
			BridgeState = SM_SOCKET_OBTAINED;
			break;

		case SM_SOCKET_OBTAINED:
			// Reset all buffers if the connection was lost
			if(TCPWasReset(MySocket))
			{
				// Optionally discard anything in the UART FIFOs
				//RXHeadPtr = vUARTRXFIFO;
				//RXTailPtr = vUARTRXFIFO;
				//TXHeadPtr = vUARTTXFIFO;
				//TXTailPtr = vUARTTXFIFO;
				
				// If we were a client socket, close the socket and attempt to reconnect
				#if defined(USE_REMOTE_TCP_SERVER)
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					BridgeState = SM_HOME;
					break;
				#endif
			}
		
			// Don't do anything if nobody is connected to us
			if(!TCPIsConnected(MySocket))
				break;
			
			
			// Make sure to clear UART errors so they don't block all future operations
			#if defined(__18CXX)
			if(RCSTAbits.OERR)
			{
				RCSTAbits.CREN = 0;
				RCSTAbits.CREN = 1;
				LED1_IO ^= 1;
			}
			if(RCSTAbits.FERR)
			{
				BYTE dummy = RCREG;
				LED2_IO ^= 1;
			}
			#else
			if(U2STAbits.OERR)
				U2STAbits.OERR = 0;
			#endif
			

			// Read FIFO pointers into a local shadow copy.  Some pointers are volatile 
			// (modified in the ISR), so we must do this safely by disabling interrupts
			RXTailPtrShadow = (BYTE*)RXTailPtr;
			TXHeadPtrShadow = (BYTE*)TXHeadPtr;
			#if defined(__18CXX)
			PIE1bits.RCIE = 0;
			PIE1bits.TXIE = 0;
			#else
			IEC1bits.U2RXIE = 0;
			IEC1bits.U2TXIE = 0;
			#endif
			RXHeadPtrShadow = (BYTE*)RXHeadPtr;
			TXTailPtrShadow = (BYTE*)TXTailPtr;
			#if defined(__18CXX)
			PIE1bits.RCIE = 1;
			if(TXHeadPtrShadow != TXTailPtrShadow)
				PIE1bits.TXIE = 1;
			#else
			IEC1bits.U2RXIE = 1;
			if(TXHeadPtrShadow != TXTailPtrShadow)
				IEC1bits.U2TXIE = 1;
			#endif

			//
			// Transmit pending data that has been placed into the UART RX FIFO (in the ISR)
			//
			wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO space
			wMaxGet = RXHeadPtrShadow - RXTailPtrShadow;	// Get UART RX FIFO byte count
			if(RXHeadPtrShadow < RXTailPtrShadow)
				wMaxGet += sizeof(vUARTRXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vUARTRXFIFO 
				// end to start address.
				w = vUARTRXFIFO + sizeof(vUARTRXFIFO) - RXTailPtrShadow;
				if(wMaxPut >= w)
				{
					TCPPutArray(MySocket, RXTailPtrShadow, w);
					RXTailPtrShadow = vUARTRXFIFO;
					wMaxPut -= w;
				}
				TCPPutArray(MySocket, RXTailPtrShadow, wMaxPut);
				RXTailPtrShadow += wMaxPut;

				// No flush.  The stack will automatically flush and do 
				// transmit coallescing to minimize the number of TCP 
				// packets that get sent.  If you explicitly call TCPFlush()
				// here, latency will go down, but so will max throughput 
				// and bandwidth efficiency.
			}

			//
			// Transfer received TCP data into the UART TX FIFO for future transmission (in the ISR)
			//
			wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
			wMaxPut = TXTailPtrShadow - TXHeadPtrShadow - 1;// Get UART TX FIFO free space
			if(TXHeadPtrShadow >= TXTailPtrShadow)
				wMaxPut += sizeof(vUARTTXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vUARTTXFIFO 
				// end to start address.
				w = vUARTTXFIFO + sizeof(vUARTTXFIFO) - TXHeadPtrShadow;
				if(wMaxPut >= w)
				{
					TCPGetArray(MySocket, TXHeadPtrShadow, w);
					TXHeadPtrShadow = vUARTTXFIFO;
					wMaxPut -= w;
				}
				TCPGetArray(MySocket, TXHeadPtrShadow, wMaxPut);
				TXHeadPtrShadow += wMaxPut;
			}
			
			// Write local shadowed FIFO pointers into the volatile FIFO pointers.
			#if defined(__18CXX)
			PIE1bits.RCIE = 0;
			PIE1bits.TXIE = 0;
			#else
			IEC1bits.U2RXIE = 0;
			IEC1bits.U2TXIE = 0;
			#endif
			RXTailPtr = (volatile BYTE*)RXTailPtrShadow;
			TXHeadPtr = (volatile BYTE*)TXHeadPtrShadow;
			#if defined(__18CXX)
			PIE1bits.RCIE = 1;
			if(TXHeadPtrShadow != TXTailPtrShadow)
				PIE1bits.TXIE = 1;
			#else
			IEC1bits.U2RXIE = 1;
			if(TXHeadPtrShadow != TXTailPtrShadow)
				IEC1bits.U2TXIE = 1;
			#endif

			break;
	}
}
/*********************************************************************
 * void IO2TCPBridgeTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void IO2TCPBridgeTask(void)
{
	static enum _BridgeState
	{
		SM_HOME = 0,
		SM_SOCKET_OBTAINED
	} BridgeState = SM_HOME;
	static TCP_SOCKET MySocket = INVALID_SOCKET;
	WORD wMaxPut, wMaxGet, w;
	BYTE *RXHeadPtrShadow, *RXTailPtrShadow;
	BYTE *TXHeadPtrShadow, *TXTailPtrShadow;


	switch(BridgeState)
	{
		case SM_HOME:
			#if defined(USE_REMOTE_TCP_SERVER)
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
			#else
				MySocket = TCPOpen(0, TCP_OPEN_SERVER, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
			#endif
			
			// Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			// Eat the first TCPWasReset() response so we don't 
			// infinitely create and reset/destroy client mode sockets
			TCPWasReset(MySocket);
			
			// We have a socket now, advance to the next state
			BridgeState = SM_SOCKET_OBTAINED;
			break;

		case SM_SOCKET_OBTAINED:
			// Reset all buffers if the connection was lost
			if(TCPWasReset(MySocket))
			{
				// Optionally discard anything in the UART FIFOs
				//RXHeadPtr = vUARTRXFIFO;
				//RXTailPtr = vUARTRXFIFO;
				//TXHeadPtr = vUARTTXFIFO;
				//TXTailPtr = vUARTTXFIFO;
				
				// If we were a client socket, close the socket and attempt to reconnect
				#if defined(USE_REMOTE_TCP_SERVER)
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					BridgeState = SM_HOME;
					break;
				#endif
			}
		
			// Don't do anything if nobody is connected to us
			if(!TCPIsConnected(MySocket))
				break;
			
			if(TRUE == TxData)
			{
				//TCPPutArray(MySocket, keyinfo, 1);
				TCPPut(MySocket, keyinfo);
				TxData = FALSE;
			}	

			// No flush.  The stack will automatically flush and do 
			// transmit coallescing to minimize the number of TCP 
			// packets that get sent.  If you explicitly call TCPFlush()
			// here, latency will go down, but so will max throughput 
			// and bandwidth efficiency.
			break;
	}
}
Пример #6
0
/*****************************************************************************
  Function:
	int connect( SOCKET s, struct sockaddr* name, int namelen )

  Summary:
	This function connects to the peer communications end point.

  Description:
	The connect function assigns the address of the peer
	communications endpoint. For stream sockets, connection is
	established between the endpoints. For datagram sockets, an
	address filter is established between the endpoints until
	changed with another connect() function.

  Precondition:
	socket function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
	name - pointer to the sockaddr structure containing the
	peer address and port number.
	namelen - length of the sockaddr structure.

  Returns:
	If the connect() function succeeds, it returns 0. Otherwise,
	the value SOCKET_ERROR is returned to indicate an error
	condition. For stream based socket, if the connection is not
	established yet, connect returns SOCKET_CNXN_IN_PROGRESS.

  Remarks:
	None.
  ***************************************************************************/
int connect( SOCKET s, struct sockaddr* name, int namelen )
{
	struct BSDSocket *socket;
	struct sockaddr_in *addr;
	DWORD remoteIP;
	WORD remotePort;
	WORD localPort;

	if( s >= BSD_SOCKET_COUNT )
		return SOCKET_ERROR;

	socket = &BSDSocketArray[s];

	if( socket->bsdState < SKT_CREATED )
		return SOCKET_ERROR;

	if( (unsigned int)namelen < sizeof(struct sockaddr_in))
		return SOCKET_ERROR;

	addr = (struct sockaddr_in *)name;
	remotePort 	= addr->sin_port;
	remoteIP 	= addr->sin_addr.S_un.S_addr;

	if( remoteIP == 0u || remotePort == 0u )
		return SOCKET_ERROR;

	if( socket->SocketType == SOCK_STREAM )
	{
		switch(socket->bsdState)
		{
		case SKT_EST:
			return 0; // already established

		case SKT_IN_PROGRESS:
			if(HandlePossibleTCPDisconnection(s))
				return SOCKET_ERROR;

			if(!TCPIsConnected(socket->SocketID))
				return SOCKET_CNXN_IN_PROGRESS;

			socket->bsdState = SKT_EST;
			return 0; //success

		case SKT_CREATED:
		case SKT_BOUND:
			socket->SocketID = TCPOpen(remoteIP, TCP_OPEN_IP_ADDRESS, remotePort, TCP_PURPOSE_BERKELEY_CLIENT);
			if(socket->SocketID == INVALID_SOCKET)
				return SOCKET_ERROR;

			// Clear the first reset flag
			TCPWasReset(socket->SocketID);

			socket->isServer = FALSE;
			socket->bsdState = SKT_IN_PROGRESS;
			return SOCKET_CNXN_IN_PROGRESS;

		default:
			return SOCKET_ERROR;
		}
	}
	else
	{
		// If not explicitly bound to a local port, implicitly do the binding
		if(socket->bsdState == SKT_CREATED)
		{
			localPort = gAutoPortNumber++;
	        if(gAutoPortNumber > 5000u) // reset the port numbers
				gAutoPortNumber = 1024;

			//socket->SocketID = UDPOpen(localPort, NULL, remotePort);
			
			socket->SocketID = UDPOpenEx(0,UDP_OPEN_SERVER,localPort, remotePort);
			if(socket->SocketID == INVALID_UDP_SOCKET)
				return SOCKET_ERROR;
			socket->bsdState = SKT_BOUND;
		}
		if(socket->bsdState != SKT_BOUND)
			return SOCKET_ERROR;

		// UDP: remote port is used as a filter. Need to call connect when using
		// send/recv calls. No need to call 'connect' if using sendto/recvfrom 
		// calls.
		socket->remotePort = remotePort;
		socket->remoteIP = remoteIP;
		return 0; //success
	}
	return SOCKET_ERROR;
}
Пример #7
0
/*********************************************************************
 * Function:        void TelnetTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void TelnetTask(void)
{
	BYTE 		i;
	BYTE		vTelnetSession;
	WORD		w, w2;
	TCP_SOCKET	MySocket;
	enum
	{
		SM_HOME = 0,
		SM_PRINT_LOGIN,
		SM_GET_LOGIN,
		SM_GET_PASSWORD,
		SM_GET_PASSWORD_BAD_LOGIN,
		SM_AUTHENTICATED,
		SM_REFRESH_VALUES
	} TelnetState;
	static TCP_SOCKET hTelnetSockets[MAX_TELNET_CONNECTIONS];
	static BYTE vTelnetStates[MAX_TELNET_CONNECTIONS];
	static BOOL bInitialized = FALSE;

	// Perform one time initialization on power up
	if(!bInitialized)
	{
		for(vTelnetSession = 0; vTelnetSession < MAX_TELNET_CONNECTIONS; vTelnetSession++)
		{
			hTelnetSockets[vTelnetSession] = INVALID_SOCKET;
			vTelnetStates[vTelnetSession] = SM_HOME;
		}
		bInitialized = TRUE;
	}


	// Loop through each telnet session and process state changes and TX/RX data
	for(vTelnetSession = 0; vTelnetSession < MAX_TELNET_CONNECTIONS; vTelnetSession++)
	{
		// Load up static state information for this session
		MySocket = hTelnetSockets[vTelnetSession];
		TelnetState = vTelnetStates[vTelnetSession];

		// Reset our state if the remote client disconnected from us
		if(MySocket != INVALID_SOCKET)
		{
			if(TCPWasReset(MySocket))
				TelnetState = SM_PRINT_LOGIN;
		}
	
		// Handle session state
		switch(TelnetState)
		{
			case SM_HOME:
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen(0, TCP_OPEN_SERVER, TELNET_PORT, TCP_PURPOSE_TELNET);
				
				// Abort operation if no TCP socket of type TCP_PURPOSE_TELNET is available
				// If this ever happens, you need to go add one to TCPIPConfig.h
				if(MySocket == INVALID_SOCKET)
					break;
	
				TelnetState++;
				break;
	
			case SM_PRINT_LOGIN:
				// Make certain the socket can be written to
				if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strTitle))
					break;
				
				// Place the application protocol data into the transmit buffer.
				TCPPutROMString(MySocket, strTitle);
	
				// Send the packet
				TCPFlush(MySocket);
				TelnetState++;
	
			case SM_GET_LOGIN:
				// Make sure we can put the password prompt
				if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strPassword))
					break;
	
				// See if the user pressed return
				w = TCPFind(MySocket, '\n', 0, FALSE);
				if(w == 0xFFFFu)
				{
					if(TCPGetRxFIFOFree(MySocket) == 0u)
					{
						TCPPutROMString(MySocket, (ROM BYTE*)"\r\nToo much data.\r\n");
						TCPDisconnect(MySocket);
					}
	
					break;
				}
			
				// Search for the username -- case insensitive
				w2 = TCPFindROMArray(MySocket, (ROM BYTE*)TELNET_USERNAME, sizeof(TELNET_USERNAME)-1, 0, TRUE);
				if((w2 != 0u) || !((sizeof(TELNET_USERNAME)-1 == w) || (sizeof(TELNET_USERNAME) == w)))
				{
					// Did not find the username, but let's pretend we did so we don't leak the user name validity
					TelnetState = SM_GET_PASSWORD_BAD_LOGIN;	
				}
				else
				{
					TelnetState = SM_GET_PASSWORD;
				}
	
				// Username verified, throw this line of data away
				TCPGetArray(MySocket, NULL, w + 1);
	
				// Print the password prompt
				TCPPutROMString(MySocket, strPassword);
				TCPFlush(MySocket);
				break;
	
			case SM_GET_PASSWORD:
			case SM_GET_PASSWORD_BAD_LOGIN:
				// Make sure we can put the authenticated prompt
				if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strAuthenticated))
					break;
	
				// See if the user pressed return
				w = TCPFind(MySocket, '\n', 0, FALSE);
				if(w == 0xFFFFu)
				{
					if(TCPGetRxFIFOFree(MySocket) == 0u)
					{
						TCPPutROMString(MySocket, (ROM BYTE*)"Too much data.\r\n");
						TCPDisconnect(MySocket);
					}
	
					break;
				}
	
				// Search for the password -- case sensitive
				w2 = TCPFindROMArray(MySocket, (ROM BYTE*)TELNET_PASSWORD, sizeof(TELNET_PASSWORD)-1, 0, FALSE);
				if((w2 != 3u) || !((sizeof(TELNET_PASSWORD)-1 == w-3) || (sizeof(TELNET_PASSWORD) == w-3)) || (TelnetState == SM_GET_PASSWORD_BAD_LOGIN))
				{
					// Did not find the password
					TelnetState = SM_PRINT_LOGIN;	
					TCPPutROMString(MySocket, strAccessDenied);
					TCPDisconnect(MySocket);
					break;
				}
	
				// Password verified, throw this line of data away
				TCPGetArray(MySocket, NULL, w + 1);
	
				// Print the authenticated prompt
				TCPPutROMString(MySocket, strAuthenticated);
				TelnetState = SM_AUTHENTICATED;
				// No break
		
			case SM_AUTHENTICATED:
				if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strDisplay) + 4)
					break;
	
				TCPPutROMString(MySocket, strDisplay);
				TelnetState++;
	
				// All future characters will be bold
				TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[1m");
	
			case SM_REFRESH_VALUES:
				if(TCPIsPutReady(MySocket) >= 78u)
				{
					//[10;1]
					//"SNTP Time:    (disabled)\r\n"
					//"Analog:             1023\r\n"
					//"Buttons:         3 2 1 0\r\n"
					//"LEDs:    7 6 5 4 3 2 1 0\r\n"
		
					// Write current UTC seconds from SNTP module, if it is enable 
					// and has changed.  Note that conversion from a DWORD to an 
					// ASCII string can take a lot of CPU power, so we only print 
					// this if the value has changed.
					#if defined(STACK_USE_SNTP_CLIENT)
					{
						static DWORD dwTime;
						BYTE vTime[11];
						
						if(dwTime != SNTPGetUTCSeconds())
						{
							
							// Position cursor at Line 10, Col 15
							TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[10;15f");
							dwTime = SNTPGetUTCSeconds();
							ultoa(dwTime, vTime);
							TCPPutROMArray(MySocket, (ROM BYTE*)strSpaces, 10-strlen((char*)vTime));							
							TCPPutString(MySocket, vTime);
						}
					}
					#endif
	
					// Position cursor at Line 11, Col 21
					TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[11;21f");
	
					// Put analog value with space padding on right side for 4 characters
					TCPPutROMArray(MySocket, (ROM BYTE*)strSpaces, 4-strlen((char*)AN0String));
					TCPPutString(MySocket, AN0String);
	
					// Put Buttons
					TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[12;18f");
					TCPPut(MySocket, BUTTON3_IO ? '1':'0');
					TCPPut(MySocket, ' ');
					TCPPut(MySocket, BUTTON2_IO ? '1':'0');
					TCPPut(MySocket, ' ');
					TCPPut(MySocket, BUTTON1_IO ? '1':'0');
					TCPPut(MySocket, ' ');
					TCPPut(MySocket, BUTTON0_IO ? '1':'0');
		
		
					// Put LEDs
					TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[13;10f");
					TCPPut(MySocket, LED1_IO ? '1':'0');
					TCPPut(MySocket, ' ');
					TCPPut(MySocket, LED0_IO ? '1':'0');
		
					// Put cursor at beginning of next line
					TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[14;1f");
	
					// Send the data out immediately
					TCPFlush(MySocket);
				}
	
				if(TCPIsGetReady(MySocket))
				{
					TCPGet(MySocket, &i);
					switch(i)
					{
						case '\r':
						case 'q':
						case 'Q':
							if(TCPIsPutReady(MySocket) >= strlenpgm((ROM char*)strGoodBye))
								TCPPutROMString(MySocket, strGoodBye);
							TCPDisconnect(MySocket);
							TelnetState = SM_PRINT_LOGIN;							
							break;
					}
				}
	
				break;
		}


		// Save session state back into the static array
		hTelnetSockets[vTelnetSession] = MySocket;
		vTelnetStates[vTelnetSession] = TelnetState;
	}
}
Пример #8
0
void ModbusCmdTask(void)
{
	static enum _BridgeState
	{
		SM_HOME = 0,
		SM_SOCKET_OBTAINED
	} BridgeState = SM_HOME;
	static TCP_SOCKET MySocket = INVALID_SOCKET;

	switch(BridgeState)
	{
		case SM_HOME:

			putrsUART((ROM char*)"\r\n in modbus sm home.");

			#if defined(DEBUG_TCP_CLIENT) //客户端
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen((DWORD)"192.168.1.36", TCP_OPEN_ROM_HOST, 502, TCP_PURPOSE_MODBUS_SERVER0);
			#else //服务器
				MySocket = TCPOpen(0, TCP_OPEN_SERVER, 502, TCP_PURPOSE_MODBUS_SERVER0);
			#endif			
			// Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			// Eat the first TCPWasReset() response so we don't 
			// infinitely create and reset/destroy client mode sockets
			TCPWasReset(MySocket);

			// We have a socket now, advance to the next state
			BridgeState = SM_SOCKET_OBTAINED;
			break;

		case SM_SOCKET_OBTAINED:
			if(TCPWasReset(MySocket))
			{
				// Optionally discard anything in the UART FIFOs
				//RXHeadPtr = vUARTRXFIFO;
				//RXTailPtr = vUARTRXFIFO;
				//TXHeadPtr = vUARTTXFIFO;
				//TXTailPtr = vUARTTXFIFO;
				
				// If we were a client socket, close the socket and attempt to reconnect
				#if defined(DEBUG_TCP_CLIENT)
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					BridgeState = SM_HOME;
					break;
				#endif
			}
			// Don't do anything if nobody is connected to us
			if(!TCPIsConnected(MySocket))
			{
				break;
			}

			ModbusTcpRxHandle(MySocket);

			break;
		default:
			BridgeState = SM_HOME;
			break;
	}
}
Пример #9
0
/*********************************************************************
 * Function:        void TelnetTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void TelnetTask(void)
{
	BYTE 				i;
	WORD				w, w2;
	static TCP_SOCKET	MySocket = INVALID_SOCKET;
	static enum _TelnetState
	{
		SM_HOME = 0,
		SM_PRINT_LOGIN,
		SM_GET_LOGIN,
		SM_GET_PASSWORD,
		SM_GET_PASSWORD_BAD_LOGIN,
		SM_AUTHENTICATED,
		SM_REFRESH_VALUES,
	} 					TelnetState = SM_HOME;

	// Reset our state if the remote client disconnected from us
	if(MySocket != INVALID_SOCKET)
	{
		if(TCPWasReset(MySocket))
			TelnetState = SM_PRINT_LOGIN;
	}


	switch(TelnetState)
	{
		case SM_HOME:
			// Connect a socket to the remote TCP server
			MySocket = TCPOpen(0, TCP_OPEN_SERVER, TELNET_PORT, TCP_PURPOSE_TELNET);
			
			// Abort operation if no TCP socket of type TCP_PURPOSE_TELNET is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			TelnetState++;
			break;

		case SM_PRINT_LOGIN:
			// Make certain the socket can be written to
			if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strTitle))
				break;
			
			// Place the application protocol data into the transmit buffer.
			TCPPutROMString(MySocket, strTitle);

			// Send the packet
			TCPFlush(MySocket);
			TelnetState++;

		case SM_GET_LOGIN:
			// Make sure we can put the password prompt
			if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strPassword))
				break;

			// See if the user pressed return
			w = TCPFind(MySocket, '\n', 0, FALSE);
			if(w == 0xFFFFu)
			{
				if(TCPGetRxFIFOFree(MySocket) == 0u)
				{
					TCPPutROMString(MySocket, (ROM BYTE*)"\r\nToo much data.\r\n");
					TCPDisconnect(MySocket);
				}

				break;
			}
		
			// Search for the username -- case insensitive
			w2 = TCPFindROMArray(MySocket, (ROM BYTE*)USERNAME, sizeof(USERNAME)-1, 0, TRUE);
			if((w2 != 0) || !((sizeof(USERNAME)-1 == w) || (sizeof(USERNAME) == w)))
			{
				// Did not find the username, but let's pretend we did so we don't leak the user name validity
				TelnetState = SM_GET_PASSWORD_BAD_LOGIN;	
			}
			else
			{
				TelnetState = SM_GET_PASSWORD;
			}

			// Username verified, throw this line of data away
			TCPGetArray(MySocket, NULL, w + 1);

			// Print the password prompt
			TCPPutROMString(MySocket, strPassword);
			TCPFlush(MySocket);
			break;

		case SM_GET_PASSWORD:
		case SM_GET_PASSWORD_BAD_LOGIN:
			// Make sure we can put the authenticated prompt
			if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strAuthenticated))
				break;

			// See if the user pressed return
			w = TCPFind(MySocket, '\n', 0, FALSE);
			if(w == 0xFFFFu)
			{
				if(TCPGetRxFIFOFree(MySocket) == 0u)
				{
					TCPPutROMString(MySocket, (ROM BYTE*)"Too much data.\r\n");
					TCPDisconnect(MySocket);
				}

				break;
			}

			// Search for the password -- case sensitive
			w2 = TCPFindROMArray(MySocket, (ROM BYTE*)PASSWORD, sizeof(PASSWORD)-1, 0, FALSE);
			if((w2 != 3) || !((sizeof(PASSWORD)-1 == w-3) || (sizeof(PASSWORD) == w-3)) || (TelnetState == SM_GET_PASSWORD_BAD_LOGIN))
			{
				// Did not find the password
				TelnetState = SM_PRINT_LOGIN;	
				TCPPutROMString(MySocket, strAccessDenied);
				TCPDisconnect(MySocket);
				break;
			}

			// Password verified, throw this line of data away
			TCPGetArray(MySocket, NULL, w + 1);

			// Print the authenticated prompt
			TCPPutROMString(MySocket, strAuthenticated);
			TelnetState = SM_AUTHENTICATED;
			// No break
	
		case SM_AUTHENTICATED:
			if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strDisplay) + 4)
				break;

			TCPPutROMString(MySocket, strDisplay);
			TelnetState++;

			// All future characters will be bold
			TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[1m");

		case SM_REFRESH_VALUES:
			if(TCPIsPutReady(MySocket) >= 60u)
			{
				//[10;1]
				//"Analog:             1023\r\n"
				//"Buttons:         3 2 1 0\r\n"
				//"LEDs:    7 6 5 4 3 2 1 0\r\n"
	
				// Position cursor at Line 10, Col 21
				TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[10;21f");

				// Put analog value with space padding on right side for 4 characters
				TCPPutROMArray(MySocket, (ROM BYTE*)"    ", 4-strlen((char*)AN0String));
				TCPPutString(MySocket, AN0String);

				// Put Buttons
				TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[11;18f");
				TCPPut(MySocket, BUTTON3_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, BUTTON2_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, BUTTON1_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, BUTTON0_IO ? '1':'0');
	
	
				// Put LEDs
				TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[12;10f");
				TCPPut(MySocket, LED7_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, LED6_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, LED5_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, LED4_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, LED3_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, LED2_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, LED1_IO ? '1':'0');
				TCPPut(MySocket, ' ');
				TCPPut(MySocket, LED0_IO ? '1':'0');
	
	
				// Put cursor at beginning of next line
				TCPPutROMString(MySocket, (ROM BYTE*)"\x1b[13;1f");

				// Send the data out immediately
				TCPFlush(MySocket);
			}

			if(TCPIsGetReady(MySocket))
			{
				TCPGet(MySocket, &i);
				switch(i)
				{
					case '\r':
					case 'q':
					case 'Q':
						if(TCPIsPutReady(MySocket) >= strlenpgm((ROM char*)strGoodBye))
							TCPPutROMString(MySocket, strGoodBye);
						TCPDisconnect(MySocket);
						TelnetState = SM_PRINT_LOGIN;							
						break;
				}
			}

			break;
	}
}
Пример #10
0
/*****************************************************************************
  Function:
	int connect( SOCKET s, struct sockaddr* name, int namelen )

  Summary:
	This function connects to the peer communications end point.

  Description:
	The connect function assigns the address of the peer
	communications endpoint. For stream sockets, connection is
	established between the endpoints. For datagram sockets, an
	address filter is established between the endpoints until
	changed with another connect() function.

  Precondition:
	socket function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
	name - pointer to the sockaddr structure containing the
	peer address and port number.
	namelen - length of the sockaddr structure.

  Returns:
	If the connect() function succeeds, it returns 0. Otherwise,
	the value SOCKET_ERROR is returned to indicate an error
	condition (and errno set accordingly).
    For stream based socket, if the connection is not
	established yet, connect returns SOCKET_ERROR and
    errno = EINPROGRESS.

  Remarks:
	None.
  ***************************************************************************/
int connect( SOCKET s, struct sockaddr* name, int namelen )
{
    struct BSDSocket *socket;
    struct sockaddr_in *addr;
    uint32_t remoteIP;
    uint16_t remotePort;
    uint16_t localPort;
    IPV4_ADDR localAddr;

    if( s >= BSD_SOCKET_COUNT )
    {
        errno = EBADF;
        return SOCKET_ERROR;
    }

    socket = &BSDSocketArray[s];

    if( socket->bsdState < SKT_CREATED )
    {
        errno = EBADF;
        return SOCKET_ERROR;
    }

    if( (unsigned int)namelen < sizeof(struct sockaddr_in))
    {
        errno = EFAULT;
        return SOCKET_ERROR;
    }

    addr = (struct sockaddr_in *)name;
    remotePort 	= addr->sin_port;
    remoteIP 	= addr->sin_addr.S_un.S_addr;

    if( remoteIP == 0u || remotePort == 0u )
    {
        errno = EINVAL;
        return SOCKET_ERROR;
    }

    if( socket->SocketType == SOCK_STREAM )
    {
        switch(socket->bsdState)
        {
        case SKT_EST:
            return 0; // already established

        case SKT_IN_PROGRESS:
            if(HandlePossibleTCPDisconnection(s))
            {
                errno = ECONNREFUSED;
                return SOCKET_ERROR;
            }

            if(!TCPIsConnected(socket->SocketID))
            {
                errno = EINPROGRESS;
                return SOCKET_ERROR;
            }

            socket->bsdState = SKT_EST;
            return 0; //success

        case SKT_CREATED:
        case SKT_BOUND:
            socket->SocketID = TCPOpenClient(IP_ADDRESS_TYPE_IPV4, remotePort, (IP_MULTI_ADDRESS*)&remoteIP);
            if(socket->SocketID == INVALID_SOCKET)
            {
                errno = ENOBUFS;
                return SOCKET_ERROR;
            }

            // Clear the first reset flag
            TCPWasReset(socket->SocketID);

            localAddr.Val = socket->localIP;
            TCPSocketSetNet(socket->SocketID, _TCPIPStackIpAddToNet(&localAddr, true));
            socket->isServer = false;
            socket->bsdState = SKT_IN_PROGRESS;
            errno = EINPROGRESS;
            return SOCKET_ERROR;

        default:
            errno = ECONNRESET;
            return SOCKET_ERROR;
        }
    }
    else
    {
        // If not explicitly bound to a local port, implicitly do the binding
        if(socket->bsdState == SKT_CREATED)
        {
            IPV4_ADDR addrAny = {IP_ADDR_ANY};

            localPort = gAutoPortNumber++;
            if(gAutoPortNumber > 5000u) // reset the port numbers
                gAutoPortNumber = 1024;

            socket->SocketID = UDPOpenServer(IP_ADDRESS_TYPE_IPV4, localPort,  0);
            if(socket->SocketID == INVALID_UDP_SOCKET)
            {
                errno = ENOBUFS;
                return SOCKET_ERROR;
            }
            UDPSocketSetNet(socket->SocketID, _TCPIPStackIpAddToNet(&addrAny, true));
            socket->bsdState = SKT_BOUND;
        }
        if(socket->bsdState != SKT_BOUND)
        {
            errno = EINVAL;
            return SOCKET_ERROR;
        }

        // UDP: remote port is used as a filter. Need to call connect when using
        // send/recv calls. No need to call 'connect' if using sendto/recvfrom
        // calls.
        socket->remotePort = remotePort;
        socket->remoteIP = remoteIP;
        return 0; //success
    }

    errno = EINVAL;
    return SOCKET_ERROR;
}
Пример #11
0
/*********************************************************************
 * Function:        void CAN2TCPBridgeTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void CAN2TCPBridgeTask(void)
{
	static enum _BridgeState
	{
		SM_HOME = 0,
		SM_SOCKET_OBTAINED
	} BridgeState = SM_HOME;
	static TCP_SOCKET MySocket = INVALID_SOCKET;
	WORD wMaxPut, wMaxGet, w;
	BYTE *RXHeadPtrShadow, *RXTailPtrShadow;
	BYTE *TXHeadPtrShadow, *TXTailPtrShadow;


	switch(BridgeState)
	{
		case SM_HOME:
			#if defined(USE_REMOTE_TCP_SERVER)
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE);
			#else
			MySocket = TCPOpen(0, TCP_OPEN_SERVER, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE);
			#endif

			
			// Abort operation if no TCP socket of type TCP_PURPOSE_CAN_2_TCP_BRIDGE is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			// Eat the first TCPWasReset() response so we don't 
			// infinitely create and reset/destroy client mode sockets
			TCPWasReset(MySocket);
			
			// We have a socket now, advance to the next state
			BridgeState = SM_SOCKET_OBTAINED;
			break;

		case SM_SOCKET_OBTAINED:
			// Reset all buffers if the connection was lost
			if(TCPWasReset(MySocket))
			{
				// Optionally discard anything in the CAN FIFOs
				RXHeadPtr = vCANRXFIFO;
				RXTailPtr = vCANRXFIFO;
				TXHeadPtr = vCANTXFIFO;
				TXTailPtr = vCANTXFIFO;
				
				// If we were a client socket, close the socket and attempt to reconnect
				#if defined(USE_REMOTE_TCP_SERVER)
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					BridgeState = SM_HOME;
					break;
				#endif
			}
		
			// Don't do anything if nobody is connected to us
			if(!TCPIsConnected(MySocket))
				break;
			

			// Read FIFO pointers into a local shadow copy.  Some pointers are volatile 
			// (modified in the ISR), so we must do this safely by disabling interrupts
			RXTailPtrShadow = (BYTE*)RXTailPtr;
			TXHeadPtrShadow = (BYTE*)TXHeadPtr;
				

			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);
			CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE);

			RXHeadPtrShadow = (BYTE*)RXHeadPtr;
			TXTailPtrShadow = (BYTE*)TXTailPtr;
			

			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);		
			if(TXHeadPtrShadow != TXTailPtrShadow)
				CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE);
			//
			// Transmit pending data that has been placed into the CAN RX FIFO (in the ISR)
			//
			wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO space
			wMaxGet = RXHeadPtrShadow - RXTailPtrShadow;	// Get CAN RX FIFO byte count
			if(RXHeadPtrShadow < RXTailPtrShadow)
				wMaxGet += sizeof(vCANRXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vCANRXFIFO 
				// end to start address.
				w = vCANRXFIFO + sizeof(vCANRXFIFO) - RXTailPtrShadow;
				if(wMaxPut >= w)
				{
					TCPPutArray(MySocket, RXTailPtrShadow, w);
					RXTailPtrShadow = vCANRXFIFO;
					wMaxPut -= w;
				}
				TCPPutArray(MySocket, RXTailPtrShadow, wMaxPut);
				RXTailPtrShadow += wMaxPut;

				// No flush.  The stack will automatically flush and do 
				// transmit coallescing to minimize the number of TCP 
				// packets that get sent.  If you explicitly call TCPFlush()
				// here, latency will go down, but so will max throughput 
				// and bandwidth efficiency.
			
			}

			//
			// Transfer received TCP data into the CAN TX FIFO for future transmission (in the ISR)
			//
			wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
			wMaxPut = TXTailPtrShadow - TXHeadPtrShadow - 1;// Get CAN TX FIFO free space
			if(TXHeadPtrShadow >= TXTailPtrShadow)
				wMaxPut += sizeof(vCANTXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vCANTXFIFO 
				// end to start address.
				w = vCANTXFIFO + sizeof(vCANTXFIFO) - TXHeadPtrShadow;
				if(wMaxPut >= w)
				{
					TCPGetArray(MySocket, TXHeadPtrShadow, w);
					TXHeadPtrShadow = vCANTXFIFO;
					wMaxPut -= w;
				}
				TCPGetArray(MySocket, TXHeadPtrShadow, wMaxPut);
				TXHeadPtrShadow += wMaxPut;
			}
			
			// Write local shadowed FIFO pointers into the volatile FIFO pointers.
			
			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);
			CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE);
			
			RXTailPtr = (volatile BYTE*)RXTailPtrShadow;
			TXHeadPtr = (volatile BYTE*)TXHeadPtrShadow;
			
			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);
			if(TXHeadPtrShadow != TXTailPtrShadow)
				CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE);

			break;
	}
}
Пример #12
0
/*****************************************************************************
  Function:
	SOCKET accept(SOCKET s, struct sockaddr* addr, int* addrlen)

  Summary:
	This function accepts connection requests queued for a listening socket.

  Description:
	The accept function is used to accept connection requests
	queued for a listening socket. If a connection request is
	pending, accept removes the request from the queue, and a new
	socket is created for the connection. The original listening
	socket remains open and continues to queue new connection
	requests. The socket must be a SOCK_STREAM type socket.

  Precondition:
	listen function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to
	socket. must be bound to a local name and in listening mode.
	addr - Optional pointer to a buffer that receives the address
	of the connecting entity.
	addrlen - Optional pointer to an integer that contains the
	length of the address addr

  Returns:
	If the accept function succeeds, it returns a non-negative
	integer that is a descriptor for the accepted socket.
	Otherwise, the value SOCKET_ERROR is returned.
    (and errno set accordingly).

  Remarks:
	None.
  ***************************************************************************/
SOCKET accept(SOCKET s, struct sockaddr* addr, int* addrlen)
{
    struct BSDSocket *pListenSock;
    TCP_SOCKET_INFO remoteSockInfo;
    struct sockaddr_in *addrRemote;
    unsigned int sockCount;
    TCP_SOCKET hTCP;

    if( s >= BSD_SOCKET_COUNT )
    {
        errno = EBADF;
        return SOCKET_ERROR;
    }

    pListenSock = &BSDSocketArray[s]; /* Get the pointer to listening server socket */

    if ( pListenSock->bsdState != SKT_BSD_LISTEN )
    {
        errno = EINVAL;
        return SOCKET_ERROR;
    }
    if ( pListenSock->SocketType != SOCK_STREAM )
    {
        errno = EOPNOTSUPP;
        return SOCKET_ERROR;
    }

    for(sockCount = 0; sockCount < BSD_SOCKET_COUNT; sockCount++)
    {
        if(BSDSocketArray[sockCount].bsdState != SKT_LISTEN)
            continue;

        if(BSDSocketArray[sockCount].localPort != pListenSock->localPort)
            continue;

        hTCP = BSDSocketArray[sockCount].SocketID;

        // We don't care about connections and disconnections before we can
        // process them, so clear the reset flag
        TCPWasReset(hTCP);

        if(TCPIsConnected(hTCP))
        {
            TCPGetSocketInfo(hTCP, &remoteSockInfo);
            if(addr)
            {
                if(addrlen)
                {
                    if((unsigned int)*addrlen < sizeof(struct sockaddr_in))
                    {
                        errno = EFAULT;
                        return SOCKET_ERROR;
                    }
                    addrRemote = (struct sockaddr_in *)addr;
                    addrRemote->sin_addr.S_un.S_addr = remoteSockInfo.remoteIPaddress.v4Add.Val;
                    addrRemote->sin_port = remoteSockInfo.remotePort;
                    *addrlen = sizeof(struct sockaddr_in);
                }
            }
            BSDSocketArray[sockCount].remotePort = remoteSockInfo.remotePort;
            BSDSocketArray[sockCount].remoteIP   = remoteSockInfo.remoteIPaddress.v4Add.Val;
            BSDSocketArray[sockCount].bsdState = SKT_EST;
            return sockCount;
        }
    }

    errno = EMFILE;
    return SOCKET_ERROR;
}
Пример #13
0
/*****************************************************************************
  Function:
	int listen( SOCKET s, int backlog )

  Summary:
	The listen function sets the specified socket in a listen mode

  Description:
	This function sets the specified socket in a listen
	mode. Calling the listen function indicates that the
	application is ready to accept connection requests arriving
	at a socket of type SOCK_STREAM. The connection request is
	queued (if possible) until accepted with an accept function.
	The backlog parameter defines the maximum number of pending
	connections that may be queued.

  Precondition:
	bind() must have been called on the s socket first.

  Parameters:
	s - Socket identifier returned from a prior socket() call.
	backlog - Maximum number of connection requests that can be queued.  Note
		that each backlog requires a TCP socket to be allocated.
		Also, ensure that BSD_SOCKET_COUNT (also in tcpip_config.h) is greater
		than the backlog by at least 1 (more if you have other BSD sockets in
		use).

  Returns:
	Returns 0 on success, else return SOCKET_ERROR.
    (and errno set accordingly).

  Remarks:
	None
  ***************************************************************************/
int listen( SOCKET s, int backlog )
{
    struct BSDSocket *ps;
    SOCKET clientSockID;
    unsigned int socketcount;
    unsigned char assigned;
    IPV4_ADDR     lclAddr;

    if( s >= BSD_SOCKET_COUNT )
    {
        errno = EBADF;
        return SOCKET_ERROR;
    }

    ps = &BSDSocketArray[s];

    if(ps->SocketType != SOCK_STREAM)
    {
        errno = EOPNOTSUPP;
        return SOCKET_ERROR;
    }

    if(ps->bsdState == SKT_BSD_LISTEN)
        backlog = ps->backlog;

    if((ps->bsdState != SKT_BOUND) && (ps->bsdState != SKT_BSD_LISTEN))
    {
        errno = EINVAL;
        return SOCKET_ERROR;
    }

    while(backlog--)
    {
        assigned = 0;
        for(socketcount = 0; socketcount < BSD_SOCKET_COUNT; socketcount++)
        {
            if(BSDSocketArray[socketcount].bsdState != SKT_CLOSED)
                continue;

            clientSockID = TCPOpenServer(IP_ADDRESS_TYPE_IPV4, ps->localPort,  0);
            if(clientSockID == INVALID_SOCKET)
            {
                errno = ENOBUFS;
                return SOCKET_ERROR;
            }
            lclAddr.Val = ps->localIP;
            TCPSocketSetNet(clientSockID, _TCPIPStackIpAddToNet(&lclAddr, true));

            // Clear the first reset flag
            TCPWasReset(clientSockID);

            assigned = 1;
            ps->bsdState = SKT_BSD_LISTEN;
            ps->backlog = backlog;

            BSDSocketArray[socketcount].SocketID = clientSockID;
            BSDSocketArray[socketcount].bsdState = SKT_LISTEN;
            BSDSocketArray[socketcount].isServer = true;
            BSDSocketArray[socketcount].localPort = ps->localPort;
            BSDSocketArray[socketcount].SocketType = SOCK_STREAM;
            BSDSocketArray[socketcount].localIP = ps->localIP;
            break;
        }
        if(!assigned)
        {
            errno = EMFILE;
            return SOCKET_ERROR;
        }
    }
    return 0; //Success
}
Пример #14
0
/*********************************************************************
 * Function:        void UART2TCPBridgeTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void UART2TCPBridgeTask2(void)
{
	static enum _BridgeState
	{
		SM_HOME = 0,
		SM_SOCKET_OBTAINED
	} BridgeState = SM_HOME;
	static TCP_SOCKET MySocket = INVALID_SOCKET;
	WORD wMaxPut, wMaxGet;  //, w;
	//BYTE *RXHeadPtrShadow, *RXTailPtrShadow;
	//BYTE *TXHeadPtrShadow, *TXTailPtrShadow;
	unsigned char buffer[PACK_MAX_RX_SIZE];
	DATA_RX_PACKET_T * prx;
	DATA_TX_PACKET_T * ptx;

	switch(BridgeState)
	{
	default:
		case SM_HOME:

			putrsUART((ROM char*)"\r\n IN UART2TCPBridgeTask() home");

			#if defined(USE_REMOTE_TCP_SERVER)
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, UART1TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
			#else
				MySocket = TCPOpen(0, TCP_OPEN_SERVER, UART1TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
            #endif
			
			// Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			// Eat the first TCPWasReset() response so we don't 
			// infinitely create and reset/destroy client mode sockets
			TCPWasReset(MySocket);

			// We have a socket now, advance to the next state
			BridgeState = SM_SOCKET_OBTAINED;
			break;

		case SM_SOCKET_OBTAINED:

			//RELAY_OUT_1 = 0;

			// Reset all buffers if the connection was lost
			if(TCPWasReset(MySocket))
			{
				// Optionally discard anything in the UART FIFOs
				//RXHeadPtr = vUARTRXFIFO;
				//RXTailPtr = vUARTRXFIFO;
				//TXHeadPtr = vUARTTXFIFO;
				//TXTailPtr = vUARTTXFIFO;
				
				// If we were a client socket, close the socket and attempt to reconnect
				#if defined(USE_REMOTE_TCP_SERVER)
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					BridgeState = SM_HOME;
					break;
				#endif
			}
		
			// Don't do anything if nobody is connected to us
			if(!TCPIsConnected(MySocket))
			{	
				LED7_IO = 0;
				break;
			}
			
			LED7_IO = 1;

			// Make sure to clear UART errors so they don't block all future operations

			if(OERR2) //RCSTAbits.OERR)
			{
				//RCSTAbits.CREN = 0;
				CREN2 = 0;
				//RCSTAbits.CREN = 1;
				CREN2 = 1;
				LED1_IO ^= 1;
			}
			if(FERR2) //RCSTAbits.FERR)
			{
				BYTE dummy = RCREG2; //RCREG;
				LED2_IO ^= 1;
			}



			prx =  GetFinishedPacket();
			if(prx != NULL) {
				if(prx->finished) {
					if(prx->index > 0) {
						wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO space
						wMaxPut = (prx->index > wMaxPut)?wMaxPut:prx->index;
						if(wMaxPut > 0) {
							TCPPutArray(MySocket, &(prx->buffer[0]), wMaxPut);
							prx->index = 0;
							prx->finished = 0;
							TCPFlush(MySocket);
						}
					}
					prx->index = 0;
					prx->finished = 0;  //测试用
					//if(THISINFO)putrsUART((ROM char *)"\r\UART Bridge look at it");
				}
			}
			//PIE1bits.RCIE = 1;
			RC2IE = 1;



			wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
			if(wMaxGet > 0) {
				DATA_TX_PACKET_T * ptx = find_next_empty_tx_buffer();
				if(ptx != NULL) {
					wMaxGet = (wMaxGet > PACK_MAX_RX_SIZE)?PACK_MAX_RX_SIZE:wMaxGet;
				    TCPGetArray(MySocket,(BYTE *)&buffer[0],wMaxGet);
				    ptx = prase_in_buffer(buffer,wMaxGet);
				    if(ptx != NULL) {
					    if(ptx->index > 0) {
						    //启动发送
						    //PIE1bits.TXIE = 1;
							TX2IE = 1;
					    }
				    }
				}
			} else {
				TCPDiscard(MySocket);
			}
			break;
	}
}
Пример #15
0
/*********************************************************************
 * Function:        static void HTTPProcess(void)
 *
 * PreCondition:    HTTPInit() called and curHTTP loaded
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:		Serves the current HTTP connection in curHTTP
 *
 * Note:            None
 ********************************************************************/
static void HTTPProcess(void)
{
    WORD lenA, lenB;
	BYTE c, i;
    BOOL isDone;
	BYTE *ext;
	BYTE buffer[HTTP_MAX_HEADER_LEN+1];

    do
    {
        isDone = TRUE;

        // If a socket is disconnected at any time 
        // forget about it and return to idle state.
        if(TCPWasReset(sktHTTP))
        {
            smHTTP = SM_HTTP_IDLE;

			// Make sure any opened files are closed
			if(curHTTP.file != MPFS_INVALID_HANDLE)
			{
				MPFSClose(curHTTP.file);
				curHTTP.file = MPFS_INVALID_HANDLE;
			}
			if(curHTTP.offsets != MPFS_INVALID_HANDLE)
			{
				MPFSClose(curHTTP.offsets);
				curHTTP.offsets = MPFS_INVALID_HANDLE;
			}

			// Adjust the TCP FIFOs for optimal reception of 
			// the next HTTP request from the browser
			TCPAdjustFIFOSize(sktHTTP, 1, 0, TCP_ADJUST_GIVE_REST_TO_RX | TCP_ADJUST_PRESERVE_RX);
        }


        switch(smHTTP)
        {

        case SM_HTTP_IDLE:

			// Check how much data is waiting
			lenA = TCPIsGetReady(sktHTTP);

			// If a connection has been made, then process the request
            if(lenA)
            {// Clear out state info and move to next state
				curHTTP.ptrData = curHTTP.data;
				smHTTP = SM_HTTP_PARSE_REQUEST;
				curHTTP.isAuthorized = 0xff;
				curHTTP.hasArgs = FALSE;
				curHTTP.callbackID = TickGet() + HTTP_TIMEOUT*TICK_SECOND;
				curHTTP.callbackPos = 0xffffffff;
				curHTTP.byteCount = 0;
			}
			
			// In all cases, we break
			// For new connections, this waits for the buffer to fill
			break;

		case SM_HTTP_PARSE_REQUEST:

			// Verify the entire first line is in the FIFO
			if(TCPFind(sktHTTP, '\n', 0, FALSE) == 0xffff)
			{// First line isn't here yet
				if(TCPGetRxFIFOFree(sktHTTP) == 0)
				{// If the FIFO is full, we overflowed
					curHTTP.httpStatus = HTTP_OVERFLOW;
					smHTTP = SM_HTTP_SERVE_HEADERS;
					isDone = FALSE;
				}
				if(TickGet() > curHTTP.callbackID)
				{// A timeout has occurred
					TCPDisconnect(sktHTTP);
					smHTTP = SM_HTTP_DISCONNECT;
					isDone = FALSE;
				}
				break;
			}

			// Reset the watchdog timer
			curHTTP.callbackID = TickGet() + HTTP_TIMEOUT*TICK_SECOND;

			// Determine the request method
			lenA = TCPFind(sktHTTP, ' ', 0, FALSE);
			if(lenA > 5)
				lenA = 5;
			TCPGetArray(sktHTTP, curHTTP.data, lenA+1);

		    if ( memcmppgm2ram(curHTTP.data, (ROM void*)"GET", 3) == 0)
			    curHTTP.httpStatus = HTTP_GET;
			#if defined(HTTP_USE_POST)
		    else if ( memcmppgm2ram(curHTTP.data, (ROM void*)"POST", 4) == 0)
			    curHTTP.httpStatus = HTTP_POST;
			#endif
		    else
			{// Unrecognized method, so return not implemented
		        curHTTP.httpStatus = HTTP_NOT_IMPLEMENTED;
				smHTTP = SM_HTTP_SERVE_HEADERS;
				isDone = FALSE;
				break;
			}

			// Find end of filename
			lenA = TCPFind(sktHTTP, ' ', 0, FALSE);
			lenB = TCPFindEx(sktHTTP, '?', 0, lenA, FALSE);
			lenA = mMIN(lenA, lenB);
			
			// If the file name is too long, then reject the request
			if(lenA > HTTP_MAX_DATA_LEN - HTTP_DEFAULT_LEN - 1)
			{
				curHTTP.httpStatus = HTTP_OVERFLOW;
				smHTTP = SM_HTTP_SERVE_HEADERS;
				isDone = FALSE;
				break;
			}

			// Read in the filename and decode
			lenB = TCPGetArray(sktHTTP, curHTTP.data, lenA);
			curHTTP.data[lenB] = '\0';
			HTTPURLDecode(curHTTP.data);
			
			// Check if this is an MPFS Upload
			#if defined(HTTP_MPFS_UPLOAD)
			if(memcmppgm2ram(&curHTTP.data[1], HTTP_MPFS_UPLOAD, strlenpgm(HTTP_MPFS_UPLOAD)) == 0)
			{// Read remainder of line, and bypass all file opening, etc.
				#if defined(HTTP_USE_AUTHENTICATION)
				curHTTP.isAuthorized = HTTPAuthenticate(NULL, NULL, &curHTTP.data[1]);
				#endif
				if(curHTTP.httpStatus == HTTP_GET)
					curHTTP.httpStatus = HTTP_MPFS_FORM;
				else
					curHTTP.httpStatus = HTTP_MPFS_UP;

				smHTTP = SM_HTTP_PARSE_HEADERS;
				isDone = FALSE;
				break;
			}
			#endif
			
			// If the last character is a not a directory delimiter, then try to open the file
			// String starts at 2nd character, because the first is always a '/'
			if(curHTTP.data[lenB-1] != '/')
				curHTTP.file = MPFSOpen(&curHTTP.data[1]);
				
			// If the open fails, then add our default name and try again
			if(curHTTP.file == MPFS_INVALID_HANDLE)
			{
				// Add the directory delimiter if needed
				if(curHTTP.data[lenB-1] != '/')
					curHTTP.data[lenB++] = '/';
				
				// Add our default file name			
				// If this is a loopback, then it's an SSL connection
				if(TCPIsLoopback(sktHTTP))
				{
					strcpypgm2ram((void*)&curHTTP.data[lenB], HTTPS_DEFAULT_FILE);
					lenB += strlenpgm(HTTPS_DEFAULT_FILE);
				}
				else
				{
					strcpypgm2ram((void*)&curHTTP.data[lenB], HTTP_DEFAULT_FILE);
					lenB += strlenpgm(HTTP_DEFAULT_FILE);
				}
					
				// Try to open again
				curHTTP.file = MPFSOpen(&curHTTP.data[1]);
			}
			
			// Find the extension in the filename
			for(ext = curHTTP.data + lenB-1; ext != curHTTP.data; ext--)
				if(*ext == '.')
					break;
					
			// Compare to known extensions to determine Content-Type
			ext++;
			for(curHTTP.fileType = HTTP_TXT; curHTTP.fileType < HTTP_UNKNOWN; curHTTP.fileType++)
				if(!stricmppgm2ram(ext, (ROM void*)httpFileExtensions[curHTTP.fileType]))
					break;
			
			// Perform first round authentication (pass file name only)
			#if defined(HTTP_USE_AUTHENTICATION)
			curHTTP.isAuthorized = HTTPAuthenticate(NULL, NULL, &curHTTP.data[1]);
			#endif
			
			// If the file was found, see if it has an index
			if(curHTTP.file != MPFS_INVALID_HANDLE &&
				(MPFSGetFlags(curHTTP.file) & MPFS2_FLAG_HASINDEX) )
			{
				curHTTP.data[lenB-1] = '#';
				curHTTP.offsets = MPFSOpen(&curHTTP.data[1]);
			}

			// Read GET args, up to buffer size - 1
			lenA = TCPFind(sktHTTP, ' ', 0, FALSE);
			if(lenA != 0)
			{
				curHTTP.hasArgs = TRUE;
				
				// Trash the '?'
				TCPGet(sktHTTP, &c);

				// Verify there's enough space
				lenA--;
				if(lenA >= HTTP_MAX_DATA_LEN - 2)
				{
			        curHTTP.httpStatus = HTTP_OVERFLOW;
					smHTTP = SM_HTTP_SERVE_HEADERS;
					isDone = FALSE;
					break;
				}

				// Read in the arguments and '&'-terminate in anticipation of cookies
				curHTTP.ptrData += TCPGetArray(sktHTTP, curHTTP.data, lenA);
				*(curHTTP.ptrData++) = '&';

			}

			// Clear the rest of the line
			lenA = TCPFind(sktHTTP, '\n', 0, FALSE);
			TCPGetArray(sktHTTP, NULL, lenA + 1);

			// Move to parsing the headers
			smHTTP = SM_HTTP_PARSE_HEADERS;
			
			// No break, continue to parsing headers

		case SM_HTTP_PARSE_HEADERS:

			// Loop over all the headers
			while(1)
			{
				// Make sure entire line is in the FIFO
				lenA = TCPFind(sktHTTP, '\n', 0, FALSE);
				if(lenA == 0xffff)
				{// If not, make sure we can receive more data
					if(TCPGetRxFIFOFree(sktHTTP) == 0)
					{// Overflow
						curHTTP.httpStatus = HTTP_OVERFLOW;
						smHTTP = SM_HTTP_SERVE_HEADERS;
						isDone = FALSE;
					}
					if(TickGet() > curHTTP.callbackID)
					{// A timeout has occured
						TCPDisconnect(sktHTTP);
						smHTTP = SM_HTTP_DISCONNECT;
						isDone = FALSE;
					}
					break;
				}
				
				// Reset the watchdog timer
				curHTTP.callbackID = TickGet() + HTTP_TIMEOUT*TICK_SECOND;
				
				// If a CRLF is immediate, then headers are done
				if(lenA == 1)
				{// Remove the CRLF and move to next state
					TCPGetArray(sktHTTP, NULL, 2);
					smHTTP = SM_HTTP_AUTHENTICATE;
					isDone = FALSE;
					break;
				}
	
				// Find the header name, and use isDone as a flag to indicate a match
				lenB = TCPFindEx(sktHTTP, ':', 0, lenA, FALSE) + 2;
				isDone = FALSE;
	
				// If name is too long or this line isn't a header, ignore it
				if(lenB > sizeof(buffer))
				{
					TCPGetArray(sktHTTP, NULL, lenA+1);
					continue;
				}
				
				// Read in the header name
				TCPGetArray(sktHTTP, buffer, lenB);
				buffer[lenB-1] = '\0';
				lenA -= lenB;
		
				// Compare header read to ones we're interested in
				for(i = 0; i < HTTP_NUM_HEADERS; i++)
				{
					if(strcmppgm2ram((char*)buffer, (ROM char *)HTTPRequestHeaders[i]) == 0)
					{// Parse the header and stop the loop
						HTTPHeaderParseLookup(i);
						isDone = TRUE;
						break;
					}
				}
				
				// Clear the rest of the line, and call the loop again
				if(isDone)
				{// We already know how much to remove unless a header was found
					lenA = TCPFind(sktHTTP, '\n', 0, FALSE);
				}
				TCPGetArray(sktHTTP, NULL, lenA+1);
			}
			
			break;

		case SM_HTTP_AUTHENTICATE:
		
			#if defined(HTTP_USE_AUTHENTICATION)
			// Check current authorization state
			if(curHTTP.isAuthorized < 0x80)
			{// 401 error
				curHTTP.httpStatus = HTTP_UNAUTHORIZED;
				smHTTP = SM_HTTP_SERVE_HEADERS;
				isDone = FALSE;
				
				#if defined(HTTP_NO_AUTH_WITHOUT_SSL)
				if(!TCPIsLoopback(sktHTTP))
					curHTTP.httpStatus = HTTP_SSL_REQUIRED;
				#endif

				break;
			}
			#endif

			// Parse the args string
			*curHTTP.ptrData = '\0';
			curHTTP.ptrData = HTTPURLDecode(curHTTP.data);

			// If this is an MPFS upload form request, bypass to headers
			#if defined(HTTP_MPFS_UPLOAD)
			if(curHTTP.httpStatus == HTTP_MPFS_FORM)
			{
				smHTTP = SM_HTTP_SERVE_HEADERS;
				isDone = FALSE;
				break;
			}
			#endif
			
			// Move on to GET args, unless there are none
			smHTTP = SM_HTTP_PROCESS_GET;
			if(!curHTTP.hasArgs)
				smHTTP = SM_HTTP_PROCESS_POST;
			isDone = FALSE;
			curHTTP.hasArgs = FALSE;
			break;

		case SM_HTTP_PROCESS_GET:

			// Run the application callback HTTPExecuteGet()
			if(HTTPExecuteGet() == HTTP_IO_WAITING)
			{// If waiting for asynchronous process, return to main app
				break;
			}

			// Move on to POST data
			smHTTP = SM_HTTP_PROCESS_POST;

		case SM_HTTP_PROCESS_POST:

			#if defined(HTTP_USE_POST)
			
			// See if we have any new data
			if(TCPIsGetReady(sktHTTP) == curHTTP.callbackPos)
			{
				if(TickGet() > curHTTP.callbackID)
				{// If a timeout has occured, disconnect
					TCPDisconnect(sktHTTP);
					smHTTP = SM_HTTP_DISCONNECT;
					isDone = FALSE;
					break;
				}
			}
			
			if(curHTTP.httpStatus == HTTP_POST 
				#if defined(HTTP_MPFS_UPLOAD)
				|| (curHTTP.httpStatus >= HTTP_MPFS_UP && curHTTP.httpStatus <= HTTP_MPFS_ERROR)
				#endif
				 )
			{
				// Run the application callback HTTPExecutePost()
				#if defined(HTTP_MPFS_UPLOAD)
				if(curHTTP.httpStatus >= HTTP_MPFS_UP && curHTTP.httpStatus <= HTTP_MPFS_ERROR)
				{
					c = HTTPMPFSUpload();
					if(c == HTTP_IO_DONE)
					{
						smHTTP = SM_HTTP_SERVE_HEADERS;
						isDone = FALSE;
						break;
					}
				}
				else
				#endif
				c = HTTPExecutePost();
				
				// If waiting for asynchronous process, return to main app
				if(c == HTTP_IO_WAITING)
				{// return to main app and make sure we don't get stuck by the watchdog
					curHTTP.callbackPos = TCPIsGetReady(sktHTTP) - 1;
					break;
				} else if(c == HTTP_IO_NEED_DATA)
				{// If waiting for more data
					curHTTP.callbackPos = TCPIsGetReady(sktHTTP);
					curHTTP.callbackID = TickGet() + HTTP_TIMEOUT*TICK_SECOND;
					// If more is expected and space is available, return to main app
					if(curHTTP.byteCount > 0 && TCPGetRxFIFOFree(sktHTTP) != 0)
						break;
					else
					{// Handle cases where application ran out of data or buffer space
						curHTTP.httpStatus = HTTP_INTERNAL_SERVER_ERROR;
						smHTTP = SM_HTTP_SERVE_HEADERS;
						isDone = FALSE;
						break;
					}	
				}
			}
			#endif

			// We're done with POST
			smHTTP = SM_HTTP_PROCESS_REQUEST;
			// No break, continue to sending request

		case SM_HTTP_PROCESS_REQUEST:

			// Check for 404
            if(curHTTP.file == MPFS_INVALID_HANDLE)
            {
                curHTTP.httpStatus = HTTP_NOT_FOUND;
                smHTTP = SM_HTTP_SERVE_HEADERS;
                isDone = FALSE;
                break;
            }

			// Set up the dynamic substitutions
			curHTTP.byteCount = 0;
			if(curHTTP.offsets == MPFS_INVALID_HANDLE)
            {// If no index file, then set next offset to huge
	            curHTTP.nextCallback = 0xffffffff;
            }
            else
            {// Read in the next callback index
	            MPFSGetLong(curHTTP.offsets, &(curHTTP.nextCallback));
			}
			
			// Move to next state
			smHTTP = SM_HTTP_SERVE_HEADERS;

		case SM_HTTP_SERVE_HEADERS:

			// We're in write mode now:
			// Adjust the TCP FIFOs for optimal transmission of 
			// the HTTP response to the browser
			TCPAdjustFIFOSize(sktHTTP, 1, 0, TCP_ADJUST_GIVE_REST_TO_TX);
				
			// Send headers
			TCPPutROMString(sktHTTP, (ROM BYTE*)HTTPResponseHeaders[curHTTP.httpStatus]);
			
			// If this is a redirect, print the rest of the Location: header			   
			if(curHTTP.httpStatus == HTTP_REDIRECT)
			{
				TCPPutString(sktHTTP, curHTTP.data);
				TCPPutROMString(sktHTTP, (ROM BYTE*)"\r\n\r\n304 Redirect: ");
				TCPPutString(sktHTTP, curHTTP.data);
				TCPPutROMString(sktHTTP, (ROM BYTE*)HTTP_CRLF);
			}

			// If not GET or POST, we're done
			if(curHTTP.httpStatus != HTTP_GET && curHTTP.httpStatus != HTTP_POST)
			{// Disconnect
				smHTTP = SM_HTTP_DISCONNECT;
				break;
			}

			// Output the content type, if known
			if(curHTTP.fileType != HTTP_UNKNOWN)
			{
				TCPPutROMString(sktHTTP, (ROM BYTE*)"Content-Type: ");
				TCPPutROMString(sktHTTP, (ROM BYTE*)httpContentTypes[curHTTP.fileType]);
				TCPPutROMString(sktHTTP, HTTP_CRLF);
			}
			
			// Output the gzip encoding header if needed
			if(MPFSGetFlags(curHTTP.file) & MPFS2_FLAG_ISZIPPED)
			{
				TCPPutROMString(sktHTTP, (ROM BYTE*)"Content-Encoding: gzip\r\n");
			}
						
			// Output the cache-control
			TCPPutROMString(sktHTTP, (ROM BYTE*)"Cache-Control: ");
			if(curHTTP.httpStatus == HTTP_POST || curHTTP.nextCallback != 0xffffffff)
			{// This is a dynamic page or a POST request, so no cache
				TCPPutROMString(sktHTTP, (ROM BYTE*)"no-cache");
			}
			else
			{// This is a static page, so save it for the specified amount of time
				TCPPutROMString(sktHTTP, (ROM BYTE*)"max-age=");
				TCPPutROMString(sktHTTP, (ROM BYTE*)HTTP_CACHE_LEN);
			}
			TCPPutROMString(sktHTTP, HTTP_CRLF);
			
			// Check if we should output cookies
			if(curHTTP.hasArgs)
				smHTTP = SM_HTTP_SERVE_COOKIES;
			else
			{// Terminate the headers
				TCPPutROMString(sktHTTP, HTTP_CRLF);
				smHTTP = SM_HTTP_SERVE_BODY;
			}
	
			// Move to next stage
			isDone = FALSE;
			break;

		case SM_HTTP_SERVE_COOKIES:

			#if defined(HTTP_USE_COOKIES)
			// If the TX FIFO runs out of space, the client will never get CRLFCRLF
			// Avoid writing huge cookies - keep it under a hundred bytes max

			// Write cookies one at a time as space permits
			for(curHTTP.ptrRead = curHTTP.data; curHTTP.hasArgs != 0; curHTTP.hasArgs--)
			{
				// Write the header
				TCPPutROMString(sktHTTP, (ROM BYTE*)"Set-Cookie: ");

				// Write the name, URL encoded, one character at a time
				while((c = *(curHTTP.ptrRead++)))
				{
					if(c == ' ')
						TCPPut(sktHTTP, '+');
					else if(c < '0' || (c > '9' && c < 'A') || (c > 'Z' && c < 'a') || c > 'z')
					{
						TCPPut(sktHTTP, '%');
						TCPPut(sktHTTP, btohexa_high(c));
						TCPPut(sktHTTP, btohexa_low(c));
					}
					else
						TCPPut(sktHTTP, c);
				}
				
				TCPPut(sktHTTP, '=');
				
				// Write the value, URL encoded, one character at a time
				while((c = *(curHTTP.ptrRead++)))
				{
					if(c == ' ')
						TCPPut(sktHTTP, '+');
					else if(c < '0' || (c > '9' && c < 'A') || (c > 'Z' && c < 'a') || c > 'z')
					{
						TCPPut(sktHTTP, '%');
						TCPPut(sktHTTP, btohexa_high(c));
						TCPPut(sktHTTP, btohexa_low(c));
					}
					else
						TCPPut(sktHTTP, c);
				}
				
				// Finish the line
				TCPPutROMString(sktHTTP, HTTP_CRLF);

			}
			#endif

			// We're done, move to next state
			TCPPutROMString(sktHTTP, HTTP_CRLF);
			smHTTP = SM_HTTP_SERVE_BODY;

		case SM_HTTP_SERVE_BODY:

			isDone = FALSE;

			// Try to send next packet
			if(HTTPSendFile())
			{// If EOF, then we're done so close and disconnect
				MPFSClose(curHTTP.file);
				curHTTP.file = MPFS_INVALID_HANDLE;
				smHTTP = SM_HTTP_DISCONNECT;
				isDone = TRUE;
			}
			
			// If the TX FIFO is full, then return to main app loop
			if(TCPIsPutReady(sktHTTP) == 0)
				isDone = TRUE;
            break;

		case SM_HTTP_SEND_FROM_CALLBACK:

			isDone = TRUE;

			// Check that at least the minimum bytes are free
			if(TCPIsPutReady(sktHTTP) < HTTP_MIN_CALLBACK_FREE)
				break;

			// Fill TX FIFO from callback
			HTTPPrint(curHTTP.callbackID);
			
			if(curHTTP.callbackPos == 0)
			{// Callback finished its output, so move on
				isDone = FALSE;
				smHTTP = SM_HTTP_SERVE_BODY;
			}// Otherwise, callback needs more buffer space, so return and wait
			
			break;

		case SM_HTTP_DISCONNECT:
		
			// Loopbacks have no wait state, so all data must be retrieved first
			if(TCPIsLoopback(sktHTTP) && TCPGetTxFIFOFull(sktHTTP) != 0)
				break;

			// Make sure any opened files are closed
			if(curHTTP.file != MPFS_INVALID_HANDLE)
			{
				MPFSClose(curHTTP.file);
				curHTTP.file = MPFS_INVALID_HANDLE;
			}
			if(curHTTP.offsets != MPFS_INVALID_HANDLE)
			{
				MPFSClose(curHTTP.offsets);
				curHTTP.offsets = MPFS_INVALID_HANDLE;
			}

			TCPDisconnect(sktHTTP);
            smHTTP = SM_HTTP_IDLE;
            break;
		}
	} while(!isDone);

}
Пример #16
0
void TelnetTask(void)
{
	BYTE		vTelnetSession;
	WORD		w, w2;
	TCP_SOCKET	MySocket;
	char outstr[60];


	// Perform one time initialization on power up
	if(!bInitialized)
	{
		for(vTelnetSession = 0; vTelnetSession < MAX_TELNET_CONNECTIONS; vTelnetSession++)
		{
			hTelnetSockets[vTelnetSession] = INVALID_SOCKET;
			vTelnetStates[vTelnetSession] = SM_HOME;
		}
		bInitialized = TRUE;
	}

	// Loop through each telnet session and process state changes and TX/RX data
	for(vTelnetSession = 0; vTelnetSession < MAX_TELNET_CONNECTIONS; vTelnetSession++)
	{
		// Load up static state information for this session
		MySocket = hTelnetSockets[vTelnetSession];
		TelnetState = vTelnetStates[vTelnetSession];

		// Reset our state if the remote client disconnected from us
		if(MySocket != INVALID_SOCKET)
		{
			if(TCPWasReset(MySocket))
				TelnetState = SM_PRINT_LOGIN;
		}

		// Handle session state
		switch(TelnetState)
		{
			case SM_HOME:
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen(0, TCP_OPEN_SERVER, TELNET_PORT, TCP_PURPOSE_TELNET);
				
				// Abort operation if no TCP socket of type TCP_PURPOSE_TELNET is available
				// If this ever happens, you need to go add one to TCPIPConfig.h
				if(MySocket == INVALID_SOCKET)
					break;
	
				// Open an SSL listener if SSL server support is enabled
				#if defined(STACK_USE_SSL_SERVER)
					TCPAddSSLListener(MySocket, TELNETS_PORT);
				#endif
	
				TelnetState++;
				break;
	
			case SM_PRINT_LOGIN:
				#if defined(STACK_USE_SSL_SERVER)
					// Reject unsecured connections if TELNET_REJECT_UNSECURED is defined
					#if defined(TELNET_REJECT_UNSECURED)
						if(!TCPIsSSL(MySocket))
						{
							if(TCPIsConnected(MySocket))
							{
								TCPDisconnect(MySocket);
								TCPDisconnect(MySocket);
								break;
							}	
						}
					#endif
						
					// Don't attempt to transmit anything if we are still handshaking.
					if(TCPSSLIsHandshaking(MySocket))
						break;
				#endif

				sprintf(outstr,"%s%d%s",(char *)strTitle,AppConfig.SerialNumber,(char *)strTitle1);
			
				// Make certain the socket can be written to
				if(TCPIsPutReady(MySocket) < strlen(outstr))
					break;
				
				// Place the application protocol data into the transmit buffer.
				TCPPutString(MySocket, (BYTE *)outstr);
	
				// Send the packet
				TCPFlush(MySocket);
				TelnetState++;
	
			case SM_GET_LOGIN:
				// Make sure we can put the password prompt
				if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strPassword))
					break;
	
				// See if the user pressed return
				w = TCPFind(MySocket, '\n', 0, FALSE);
				if(w == 0xFFFFu)
				{
					if(TCPGetRxFIFOFree(MySocket) == 0u)
					{
						TCPPutROMString(MySocket, (ROM BYTE*)"\r\nToo much data.\r\n");
						TCPDisconnect(MySocket);
					}
	
					break;
				}
			
				// Search for the username -- case insensitive
				w2 = TCPFindArray(MySocket, TELNET_USERNAME, strlen((char*)TELNET_USERNAME), 0, TRUE);
				if((w2 < 0) || !((w2 == ((w - strlen((char *)TELNET_USERNAME)) - 1)) || (w2 == (w - strlen((char *)TELNET_USERNAME)))))
				{
					// Did not find the username, but let's pretend we did so we don't leak the user name validity
					TelnetState = SM_GET_PASSWORD_BAD_LOGIN;	
				}
				else
				{
					TelnetState = SM_GET_PASSWORD;
				}
	
				// Username verified, throw this line of data away
				TCPGetArray(MySocket, NULL, w + 1);
	
				// Print the password prompt
				TCPPutROMString(MySocket, strPassword);
				TCPFlush(MySocket);
				break;
	
			case SM_GET_PASSWORD:
			case SM_GET_PASSWORD_BAD_LOGIN:
				// Make sure we can put the authenticated prompt
				if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)strAuthenticated))
					break;
	
				// See if the user pressed return
				w = TCPFind(MySocket, '\n', 0, FALSE);
				if(w == 0xFFFFu)
				{
					if(TCPGetRxFIFOFree(MySocket) == 0u)
					{
						TCPPutROMString(MySocket, (ROM BYTE*)"Too much data.\r\n");
						TCPDisconnect(MySocket);
					}
	
					break;
				}
	
				// Search for the password -- case sensitive
				w2 = TCPFindArray(MySocket, TELNET_PASSWORD, strlen((char *)TELNET_PASSWORD), 0, FALSE);

				if((w2 != 3u) || !(((strlen((char *)TELNET_PASSWORD) == w-4)) || ((strlen((char *)TELNET_PASSWORD) == w-3)))
					|| (TelnetState == SM_GET_PASSWORD_BAD_LOGIN))
				{
					// Did not find the password
					TelnetState = SM_PRINT_LOGIN;	
					TCPPutROMString(MySocket, strAccessDenied);
					TCPDisconnect(MySocket);
					break;
				}
	
				// Password verified, throw this line of data away
				TCPGetArray(MySocket, NULL, w + 1);
	
				// Print the authenticated prompt
				TCPPutROMString(MySocket, strAuthenticated);
				TCPFlush(MySocket);
				TelnetState = SM_AUTHENTICATED;
				// No break
		
			case SM_AUTHENTICATED:
				break;
		}
		// Save session state back into the static array
		hTelnetSockets[vTelnetSession] = MySocket;
		vTelnetStates[vTelnetSession] = TelnetState;
	}
}