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; } }
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 ); }
/********************************************************************* * 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; }
/********************************************************************* * 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); }
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; } }