Exemple #1
0
static char HTTP_SetBuf(unsigned len)
{
	// Clear out any previously buffered data
	HTTP_FlushBuf();

	// Is the desired maximum amount of data already present?
	if(TCPIsGetReady(HTTP.socket) < len)
	{
		// Search for the CRLF deliminating the end of the line 
		// to Verify the entire first line is in the FIFO
		len = TCPFindROMArray(HTTP.socket, (ROM BYTE*)"\r\n", 2, 0, false);

		if(len == 0xFFFFu)
		{
			// Nothing yet..
			if(!TCPGetRxFIFOFree(HTTP.socket))
			{// If the FIFO is full, we overflowed
				HTTP.StateMachine = SM_HTTP_ERROR;
				HTTP.Status = HTTP_OVERFLOW;
				HTTP.FileType = HTTP_ERR_LINE_TOO_LONG;
			}
			return 0;
		}

		// Include the newlines themselves
		len += 2;
	}

	// Prepare the buffer
	HTTP_Buffer.read = &HTTP_Data[HTTP_MAX_DATA_LEN];
	HTTP_Buffer.write = HTTP_Data;
	HTTP_Buffer.remaining = len;
	return 1;
}
/*********************************************************************
 * 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;
	}
}
Exemple #3
0
static void HTTPProcess(HTTP_HANDLE h) {
	char bafs[26], r;

	BOOL lbContinue;
	static HTTP_INFO* ph;
	WORD w;
	static BYTE *p, *t;

	ph = &HCB[h];
    do {
		lbContinue = FALSE;
        if(!TCPIsConnected(ph->socket)) { 	ph->smHTTP = SM_HTTP_IDLE;  break; }

        switch(ph->smHTTP) {
        case SM_HTTP_IDLE:
			w = TCPGetArray(ph->socket, httpData, MAX_HTML_CMD_LEN);
			if(!w) {
				if(TCPGetRxFIFOFree(ph->socket) == 0) TCPDisconnect(ph->socket); // Request is too big, we can't support it.
				break;
			}
			httpData[w] = 0;
			t = p = httpData;
			while(*p)	if(*p=='%') { *t++ = hex2bin(p+1); p += 3; } else *t++ = *p++;	*t = 0;
			r = httpData[150];  httpData[150]=0;

			lbContinue = TRUE;
			ph->smHTTP = SM_HTTP_NOT_FOUND;
			if(strstrrampgm(httpData,"POST"))	ph->smHTTP = SM_HTTP_POST;
			if(strstrrampgm(httpData,"GET")) {
				ph->smHTTP = SM_HTTP_HEADER;
#ifndef _FAVICON_
				if(strstrrampgm(httpData,(ROM void*)"favicon"))		{ TCPDisconnect(ph->socket);  ph->smHTTP = SM_HTTP_IDLE; }
#else
				if(strstrrampgm(httpData,"favicon"))		ph->smHTTP = SM_ICO_HEADER;
#endif
				if(strstrrampgm(httpData, "Sw_Pool"))		AppConfig.who ^= 0x81;
				if(strstrrampgm(httpData, "Sw_Mode"))		AppConfig.sw_mode ^= 1;
				if(strstrrampgm(httpData, "Sw_Clock"))		AppConfig.CkSel ^= 1;
				if(strstrrampgm(httpData, "Sw_LEDs"))		bLEDs ^= 1;
			}
			httpData[150]=r;
			break;
            
        case SM_HTTP_POST:
			exoit(ph->socket);
			memcpypgm2ram(spwrk,rMinPool,SZ_ROMS );
			for(r=0;r<SZ_SRCH;r++) {
				BYTE *s;
				p = strstrrampgm(httpData,(ROM BYTE*)(DWORD)sComa[r]);
				if(p) {
					p+=5;
					t=strstrrampgm(p,ampa);
					if(t) {
						*t=0; s=p;
						switch(r) {
//							case C_JMAC:	Hex2Mac(p); break; //S2Mac(p);	break;
							case C_JMIP:	StringToIPAddress(p,&AppConfig.MyIPAddr); break;
							case C_JMSK:	StringToIPAddress(p,&AppConfig.MyMask); break;
							case C_JGTW:	StringToIPAddress(p,&AppConfig.MyGateway); break;
							case C_PDNS:	StringToIPAddress(p,&AppConfig.PrimaryDNSServer); break;
							case C_SDNS:	StringToIPAddress(p,&AppConfig.SecondaryDNSServer); break;
							case C_WPRT:	AppConfig.MyPort = atoi(p); break;
							case C_MPRT:	while(*p) if((*p) == ',')	{ *p=0; AppConfig.MinPort[0] = atoi(s); break; } else p++;
											AppConfig.MinPort[1] = atoi(++p); *--p = ',';
											break;
							case C_MURL:	while(*p) if((*p) == ',')	{ *p=0; strcpy(&spwrk[0],s); break; } else p++;
											strcpy(&spwrk[sizeof(rMinPool)/2],++p); *--p = ',';
											break;
							case C_USPA:	while(*p) if((*p) == ',')	{ *p=0; strcpy(&spwrk[sizeof(rMinPool)],s); break; } else p++;
											strcpy(&spwrk[sizeof(rMinPool)+sizeof(rUsrPass)/2],++p); *--p = ',';
											break;
						}
						*t='&';
					}
				}
			}
			ph->smHTTP = SM_HTTP_IDLE; 		SetUPS();
	       	break;

        case SM_HTTP_NOT_FOUND:
			if(TCPIsPutReady(ph->socket) >= sizeof(hdrErr)) {
				TCPPutROMString(ph->socket, hdrErr); TCPFlush(ph->socket);
				TCPDisconnect(ph->socket);
				ph->smHTTP = SM_HTTP_IDLE;
            }
            break;
#ifdef _FAVICON_
        case SM_ICO_HEADER:
			if ( TCPIsPutReady(ph->socket) ) {
                lbContinue = TRUE;
				if(TCPIsPutReady(ph->socket) >= sizeof(hdrICO)+198) {
                	TCPPutROMString(ph->socket, hdrICO);
					TCPPutROMArray(ph->socket, favicon,198);
					TCPFlush(ph->socket);
					TCPDisconnect(ph->socket);
                	ph->smHTTP = SM_HTTP_IDLE;
				}
			}
			break;
#endif
        case SM_HTTP_HEADER:
            if ( TCPIsPutReady(ph->socket) ) {
                lbContinue = TRUE;
				if(TCPIsPutReady(ph->socket) >= sizeof(hdrOK)) {
                	TCPPutROMString(ph->socket, hdrOK);
					TCPFlush(ph->socket);
                	ph->smHTTP = SM_HTTP_GET;
                	ph->Pos = Page;
            	}
            }
            break;

        case SM_HTTP_GET:
			TCPDiscard(ph->socket);
			if(TCPIsPutReady(ph->socket) >= 400) {
				ph->Pos = TCPPutROMString(ph->socket, ph->Pos);
				ph->Pos++;
				switch (*ph->Pos) {
					case  0: TCPDisconnect(ph->socket); ph->smHTTP = SM_HTTP_IDLE; ph->Pos = Page; break;
					case  1: DoStic(ph->socket, 1); break;
					case  2: DoStic(ph->socket, 2); break;
					case  3: DoStic(ph->socket, 3); break;
//					case  4: MAC2Hex(bafs); TCPPutString(ph->socket, bafs); break;
					case  5: IP2String(AppConfig.MyIPAddr,bafs); TCPPutString(ph->socket, bafs); break;
					case  6: IP2String(AppConfig.MyMask,bafs); TCPPutString(ph->socket, bafs); break;
					case  7: IP2String(AppConfig.MyGateway,bafs); TCPPutString(ph->socket, bafs); break;
					case  8: uitoa(AppConfig.MyPort,bafs); TCPPutString(ph->socket, bafs); break;
					case  9: IP2String(AppConfig.PrimaryDNSServer,bafs); TCPPutString(ph->socket, bafs); break;
					case 10: IP2String(AppConfig.SecondaryDNSServer,bafs); TCPPutString(ph->socket, bafs); break;
					case 11: uitoa(AppConfig.MinPort[0],bafs); TCPPutString(ph->socket, bafs); TCPPut(ph->socket,','); uitoa(AppConfig.MinPort[1],bafs); TCPPutString(ph->socket, bafs); break;
					case 12: TCPPutROMString(ph->socket, rMinPool[0]); TCPPut(ph->socket,','); TCPPutROMString(ph->socket, rMinPool[1]); break;
					case 13: TCPPutROMString(ph->socket, rUsrPass[0]); TCPPut(ph->socket,','); TCPPutROMString(ph->socket, rUsrPass[1]); break;
				}
				ph->Pos++;
			}
			TCPFlush(ph->socket);
			break;
		default:	break;
        }
    } while( lbContinue );
}
Exemple #4
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;
	}
}
/*****************************************************************************
  Function:
	static HTTP_IO_RESULT HTTPPostWifiConfig(void)

  Summary:
	Processes the wifi config data

  Description:
	Accepts wireless configuration data from the www site and saves them to a
	structure to be applied by the ZG configuration manager.

    The following configurations are possible:
         i) Mode: adhoc or infrastructure
        ii) Security:
               - None
               - WPA/WPA2 passphrase
               - WPA/WPA2 pre-calculated key
               - WEP 64-bit
               - WEP 128-bit
       iii) Key material
	
	If an error occurs, such as data is invalid they will be redirected to a page
    informing the user of such results.  

    NOTE: This code for modified originally from HTTPPostWifiConfig as distributed
          by Microchip.

  Precondition:
	None

  Parameters:
	None

  Return Values:
  	HTTP_IO_DONE - all parameters have been processed
  	HTTP_IO_NEED_DATA - data needed by this function has not yet arrived
  ***************************************************************************/
static HTTP_IO_RESULT HTTPPostWifiConfig(void)
{
	// Check to see if the browser is attempting to submit more data than we 
	// can parse at once.  This function needs to receive all updated 
	// parameters and validate them all before committing them to memory so that
	// orphaned configuration parameters do not get written (for example, if a 
	// static IP address is given, but the subnet mask fails parsing, we 
	// should not use the static IP address).  Everything needs to be processed 
	// in a single transaction.  If this is impossible, fail and notify the user.
	// As a web devloper, if you add parameters to AppConfig and run into this 
	// problem, you could fix this by to splitting your update web page into two 
	// seperate web pages (causing two transactional writes).  Alternatively, 
	// you could fix it by storing a static shadow copy of AppConfig someplace 
	// in memory and using it instead of newAppConfig.  Lastly, you could 
	// increase the TCP RX FIFO size for the HTTP server.  This will allow more 
	// data to be POSTed by the web browser before hitting this limit.

    UINT8 ConnectionProfileID;
    UINT8 ConnectionState;
    UINT8 ssidLen;

    WF_CMGetConnectionState(&ConnectionState, &ConnectionProfileID);

	if(curHTTP.byteCount > TCPIsGetReady(sktHTTP) + TCPGetRxFIFOFree(sktHTTP))
		goto ConfigFailure;
	
	// Ensure that all data is waiting to be parsed.  If not, keep waiting for 
	// all of it to arrive.
	if(TCPIsGetReady(sktHTTP) < curHTTP.byteCount)
		return HTTP_IO_NEED_DATA;
	
	// Read all browser POST data
	while(curHTTP.byteCount)
	{
		// Read a form field name
		if(HTTPReadPostName(curHTTP.data, 6) != HTTP_READ_OK)
			goto ConfigFailure;
			
		// Read a form field value
		if(HTTPReadPostValue(curHTTP.data + 6, sizeof(curHTTP.data)-6-2) != HTTP_READ_OK)
			goto ConfigFailure;
			
		// Parse the value that was read
        // Read security type
		if(!strcmppgm2ram((char*)curHTTP.data, "sec"))
		{
            char   security_type[7];

            if (strlen((char*)(curHTTP.data+6)) > 6) /* Sanity check */
                goto ConfigFailure;

            memcpy(security_type, (void*)(curHTTP.data+6), strlen((char*)(curHTTP.data+6)));
            security_type[strlen((char*)(curHTTP.data+6))] = 0; /* Terminate string */
            
            printf("\r\nSecurity Mode: ");
		    if (!strcmppgm2ram((char*)security_type, "no"))
            {
                CFGCXT.security = WF_SECURITY_OPEN;
                printf("OPEN");
            }
		    else if(!strcmppgm2ram((char*)security_type, "wpa")) 
            {
                CFGCXT.security = WF_SECURITY_WPA_AUTO_WITH_PASS_PHRASE;
                printf("WPA w/PASSPHRASE");
            }
		    else if(!strcmppgm2ram((char*)security_type, "calc")) 
            {   /* Pre-calculated key */
                CFGCXT.security = WF_SECURITY_WPA_AUTO_WITH_KEY;
                printf("WPA w/AUTO Key");
            }
		    else if(!strcmppgm2ram((char*)security_type, "wep40"))
            {
                CFGCXT.security = WF_SECURITY_WEP_40;
                printf("WEP 64-bit");
            }
		    else if(!strcmppgm2ram((char*)security_type, "wep104"))
            {
                CFGCXT.security = WF_SECURITY_WEP_104;
                printf("WEP 128-bit");
            }
		    else 
            {   //Security type no good  :-(
                printf("\r\nUnknown key type!");
                goto ConfigFailure;
            }				
		}
        // Read new Security Key
		/*
		else if(!strcmppgm2ram((char*)curHTTP.data, "key"))
		{
            BYTE key_size = 0, ascii_key = 0;

            switch ((BYTE)CFGCXT.security)
            {
                case WF_SECURITY_OPEN:   //keep compiler happy, nothing to do here!
                    break;

                case WF_SECURITY_WPA_AUTO_WITH_PASS_PHRASE:  //wpa passphrase
                    printf("\r\nPassphrase type of key! ");
                    ascii_key = 1;
                    key_size = strlen((char *)(curHTTP.data+6));
                    //between 8-63 characters, passphrase
                    if ((key_size < 8 ) || (key_size > 63))
                          goto ConfigFailure;
                    break;

                case WF_SECURITY_WPA_AUTO_WITH_KEY: //wpa pre-calculated key!!!
                    key_size = 64;
                    break;

                case WF_SECURITY_WEP_40:
                    key_size = 10; // Assume hex size
                    if (strlen((char *)(curHTTP.data+6)) == 5) {
                        key_size = 5;  // ASCII key support
                        ascii_key = 1;
                     } 
                    CFGCXT.defaultWepKey = 0; // Example uses only key idx 0 (sometimes called 1)
                    break;

                case WF_SECURITY_WEP_104:
                    key_size = 26; // Assume hex size
                    if (strlen((char *)(curHTTP.data+6)) == 13) {
                        key_size = 13;  // ASCII key support
                        ascii_key = 1;
                    } 
                    CFGCXT.defaultWepKey = 0; // Example uses only key idx 0 (sometimes called 1)
                    break;

                default:
                    break;
			}

			if (strlen((char *)(curHTTP.data + 6)) != key_size)
			{
				printf("\r\nIncomplete key received! ");
				goto ConfigFailure;
			}
			memcpy(CFGCXT.key, (void*)(curHTTP.data+6), key_size);
			CFGCXT.key[key_size] = 0; // terminate string
			if (!ascii_key)
			{
				//if ((cfg.security == sec_wep64) || (cfg.security == sec_wep128))
				key_size /= 2;
				if (!convertAsciiToHexInPlace((INT8 *)&CFGCXT.key[0], key_size))
				{
					printf("\r\nFailed to convert ASCII to hex! ");
					goto ConfigFailure;
				}
			}
		}
		*/
        // Get new ssid and make sure it is valid
		else if(!strcmppgm2ram((char*)curHTTP.data, "ssid"))
		{
			if(strlen((char*)(curHTTP.data+6)) < 33u)
			{
                memcpy(CFGCXT.ssid, (void*)(curHTTP.data+6), strlen((char*)(curHTTP.data+6)));
                CFGCXT.ssid[strlen((char*)(curHTTP.data+6))] = 0; /* Terminate string */

                /* save current profile SSID for displaying later */
                WF_CPGetSsid(ConnectionProfileID, (UINT8*)&CFGCXT.prevSSID, &ssidLen);
                CFGCXT.prevSSID[ssidLen] = 0;
                printf("\r\nSSID: %s",CFGCXT.ssid);
			}
			else
			{   //Invalid SSID... fail :-(
                printf("\r\nInvalid SSID...! ");
				goto ConfigFailure;
			}
		}
        // Get the wlan mode: adhoc or infrastructure
		else if(!strcmppgm2ram((char*)curHTTP.data, (ROM char*)"wlan"))
		{
            char mode[6];

            if (strlen((char*)(curHTTP.data+6)) > 5) /* Sanity check */
                goto ConfigFailure;

            memcpy(mode, (void*)(curHTTP.data+6), strlen((char*)(curHTTP.data+6)));
            mode[strlen((char*)(curHTTP.data+6))] = 0; /* Terminate string */
		    if(!strcmppgm2ram((char*)mode, (ROM char*)"infra"))
            {
                printf("\r\nSetting mode to infrastructure! ");
                CFGCXT.type = WF_INFRASTRUCTURE;
            }
		    else if(!strcmppgm2ram((char*)mode, "adhoc")) 
            {
                printf("\r\nSetting mode to adhoc! ");
                CFGCXT.type = WF_ADHOC;

                // Always setup adhoc to attempt to connect first, then start
                WF_CPSetAdHocBehavior(ConnectionProfileID, WF_ADHOC_CONNECT_THEN_START);
            }
		    else 
            {   //Mode type no good  :-(
                printf("\r\nConfig WLAN Mode Failure! ");
                goto ConfigFailure;
            }

            // save old WLAN mode
            WF_CPGetNetworkType(ConnectionProfileID, &CFGCXT.prevWLAN);				
		}
	}

    /* Check if WPA hasn't been selected with adhoc, if it has we choke! */
    if ((CFGCXT.type == WF_ADHOC) &&
      ((CFGCXT.security == WF_SECURITY_WPA_AUTO_WITH_PASS_PHRASE) || (CFGCXT.security == WF_SECURITY_WPA_AUTO_WITH_KEY)))
        goto ConfigFailure;

	/* 
     * All parsing complete!  If we have got to here all data has been validated and
     * we can handle what is necessary to start the reconfigure process of the WiFi device
     */
    // Copy wifi cfg data to be committed
    memcpy(CPElements.ssid, CFGCXT.ssid, strlen((char*)(CFGCXT.ssid)));
    CPElements.ssidLength = strlen((char*)(CFGCXT.ssid));
    /* Going to set security type */
    CPElements.securityType = CFGCXT.security;
    /* Going to save the key, if required */
    if (CFGCXT.security != WF_SECURITY_OPEN)
    {
        BYTE  key_size =0;

        switch ((BYTE)CFGCXT.security)
        {
            case WF_SECURITY_WPA_AUTO_WITH_PASS_PHRASE:  //wpa passphrase
                key_size = strlen((char*)(CFGCXT.key)); //ascii so use strlen
                break;
            case WF_SECURITY_WPA_AUTO_WITH_KEY: //wpa pre-calculated key!!!
                key_size = 32;
                break;
            case WF_SECURITY_WEP_40:
                key_size = 5;
                break;
            case WF_SECURITY_WEP_104:
                key_size = 13;
                break;

        }
        memcpy(CPElements.securityKey, CFGCXT.key, key_size);
        CPElements.securityKey[strlen((char*)(CFGCXT.key))] = 0;
    }
    /* Going to save the network type */
    CPElements.networkType = CFGCXT.type;

	// Set the board to reboot and display reconnecting information
	strcpypgm2ram((char*)curHTTP.data, "/reconnect.htm");
	curHTTP.httpStatus = HTTP_REDIRECT;	

    /*
     * Set state here to inform that the Wifi device has config data and it is ready
     * to be acted upon.
     */
    printf("\r\nFlagging to start config change!\r\n");

	WF_START_EASY_CONFIG();

	return HTTP_IO_DONE;

ConfigFailure:
	//!lastFailure = TRUE;
	strcpypgm2ram((char*)curHTTP.data, "/error.htm");
	curHTTP.httpStatus = HTTP_REDIRECT;		

	return HTTP_IO_DONE;
}
Exemple #6
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);

}
Exemple #7
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;
	}
}