/*** void TcpClient::discardReadBuffer(void) ** ** Synopsis: ** Empties (flushes) the input (read) buffer. ** All bytes are discarded. ** ** Parameters: ** None ** ** Return Values: ** None ** ** Errors: ** None ** ** Notes: ** ** This call is safe to make without checking the connection status. ** */ void TcpClient::discardReadBuffer(void) { // run periodic tasks, and finish a connection isConnected(DNETcK::msImmediate); if(_hTCP < INVALID_SOCKET) { // clean out the buffer TCPDiscard(_hTCP); } }
/*** void TCPSocket::close(void) ** ** Synopsis: ** Closes the socket and clears the TCPSocket instance; ** Returns the instance to a just constructed state releasing ** all resources. ** ** Parameters: ** None ** ** Return Values: ** None ** ** Errors: ** None ** ** Notes: ** ** Returns the TCPSocket instance to ** a state just as if the instance had just been ** constructed. It also, Close the connection if ** if it is still active. ** */ void TCPSocket::close(void) { if(_classState != ipsNotInitialized) { // clean out the buffer TCPDiscard(&_socket); // release the resources back to stack TCPClose(&_socket, NULL); } // reset our member variables clear(false); }
/*** void TcpClient::close(void) ** ** Synopsis: ** Closes the socket and clears the TcpClient instance; ** Returns the instance to a just constructed state releasing ** all resources. ** ** Parameters: ** None ** ** Return Values: ** None ** ** Errors: ** None ** ** Notes: ** ** Returns the TcpClient instance to ** a state just as if the instance had just been ** constructed. It also, Close the connection if ** if it is still active. ** */ void TcpClient::close(void) { if(_hTCP < INVALID_SOCKET) { // clean out the buffer TCPDiscard(_hTCP); // release the resources back to the MAL TCPClose(_hTCP); } // we are just closed _hTCP = INVALID_SOCKET; _classState = DNETcK::NotConnected; // say the enpoints are gone too _fEndPointsSetUp = false; }
/**************************************************************************** Function: TCP_SOCKET ChipKITClientConnect(unsigned int dwOpenVal, BYTE vRemoteHostType, unsigned short wPort, unsigned int cSecTimout) Description: This routine opens a socket and for clients only, attempts to connect to the server. DNS lookups are done if a URL is specifed for dwOpenVal and vRemoteHostType == TCP_OPEN_RAM_HOST Precondition: None Parameters: dwOpenVal - Same as in TCPOpen vRemoteHostType - Same as in TCPOpen wPort - Same as in TCPOpen cSecTimout - If this is a client connecting to a host, this is the number of seconds to wait for a successful connection to occur Returns: The valid socket if the open was successful, or INVALID_SOCKET if no sockets were avaiable or the connection was not made (in the case of a client) Remarks: This routine will attempt to wait until the connection is made for client, but will return immediately for servers as servers listen for connections. For the client case, if cSecTimout is exceeded, the connection is close and the socket released back to the stack for reuse. ***************************************************************************/ TCP_SOCKET ChipKITClientConnect(unsigned int dwOpenVal, BYTE vRemoteHostType, unsigned short wPort, unsigned int cSecTimout) { TCP_SOCKET hTCP = UNKNOWN_SOCKET; DWORD t = 0; hTCP = TCPOpen((DWORD) dwOpenVal, vRemoteHostType, (WORD) wPort, TCP_PURPOSE_DEFAULT); ChipKITPeriodicTasks(); // if it just fails, don't even attempt a retry if(hTCP == INVALID_SOCKET) { return(hTCP); } // if this is a client, we have to wait until we connect // No need to do this for servers as they connect when some one comes in on the listen if(vRemoteHostType != TCP_OPEN_SERVER) { t = TickGet(); // so we don't loop forever while(!TCPIsConnected(hTCP)) { ChipKITPeriodicTasks(); // if after 10 seconds we do not connect, just fail and clean up if( (TickGet() - t) >= (cSecTimout * TICK_SECOND)) { TCPClose(hTCP); TCPDiscard(hTCP); hTCP = INVALID_SOCKET; // make sure we run tasks again to get for the close to take effect // so don't return here, break out of the while to clean up break; } } ChipKITPeriodicTasks(); } return(hTCP); }
/*** void TcpServer::close(void) ** ** Synopsis: ** Stops Listening and closes all unaccepted sockets/connections ** and clears everything back to it's originally constructed state. ** ** Parameters: ** None ** ** Return Values: ** None ** ** Errors: ** None ** ** Notes: ** ** Returns the TcpServer instance to ** a state just as if the instance had just been ** constructed. It also, Close all connections ** and releases all resources (sockets). ** */ void TcpServer::close(void) { stopListening(); for(int i = 0; i<_cMaxPendingAllowed; i++) { if(_rghTCP[i] < INVALID_SOCKET) { // clean out the buffer TCPDiscard(_rghTCP[i]); // release the resources back to the MAL TCPClose(_rghTCP[i]); // invalidate the socket _rghTCP[i] = INVALID_SOCKET; } } clear(); }
/**************************************************************************** Function: void ChipKITClientStop(TCP_SOCKET hTCP) Description: This routine closes the socket, discards the input buffer, and returns the socket to the TCPIP stack. Precondition: hTCP must be open and valid. Parameters: hTCP - The socket to close Returns: none Remarks: This is to match functionality of the Arduino Client class stop method ***************************************************************************/ void ChipKITClientStop(TCP_SOCKET hTCP) { // the MAL can hang if you attempt to close an invalid socket if(hTCP == INVALID_SOCKET || hTCP == UNKNOWN_SOCKET) { return; } // close the handle TCPClose(hTCP); // empty the receive buffer because we are killing it. TCPDiscard(hTCP); // loop until it is acknowledged to be closed do { ChipKITPeriodicTasks(); } while(TCPIsConnected(hTCP)); }
/*** void TcpServer::stopListening(void) ** ** Synopsis: ** This stops listening on the server port, but does not shutdown TcpServer ** ** Parameters: ** None ** ** Return Values: ** None ** ** Errors: ** None ** ** Notes: ** To resume listening, just call ResumeListening ** This is a soft stop listening in that only the server stops listening on the port ** however the instance is still valid and you can continue to accept pending client. ** and you can resume the listening. ** */ void TcpServer::stopListening(void) { // DO NOT blow away pending clients. // that will be done on a close() // update the pending count so we have them all. availableClients(); if(_cPending < _cPendingMax && _rghTCP[_cPending] < INVALID_SOCKET) { // clean out the buffer TCPDiscard(_rghTCP[_cPending]); // release the resources back to the MAL TCPClose(_rghTCP[_cPending]); // only invalidate if this is the listening socket _rghTCP[_cPending] = INVALID_SOCKET; } // no longer listening _fListening = false; }
/**************************************************************************** Function: void ChipKITClientFlush(TCP_SOCKET hTCP) Description: This routine discards any bytes in the socket input buffer Precondition: hTCP must be open and valid. Parameters: hTCP - The socket to check Returns: none. Remarks: This is to match functionality of the Arduino Client class flush method In Arduino, flush means to discard the input buffer which is different than Flush in the MAL which means to push the data out on the wire. ***************************************************************************/ void ChipKITClientFlush(TCP_SOCKET hTCP) { TCPDiscard(hTCP); ChipKITPeriodicTasks(); }
static HTTP_IO_RESULT HTTPMPFSUpload(void) { BYTE c[16]; WORD lenA, lenB; switch(curHTTP.httpStatus) { // New upload, so look for the CRLFCRLF case HTTP_MPFS_UP: lenA = TCPFindROMArray(sktHTTP, (ROM BYTE*)"\r\n\r\n", 4, 0, FALSE); if(lenA != 0xffff) {// Found it, so remove all data up to and including lenA = TCPGetArray(sktHTTP, NULL, lenA); curHTTP.byteCount -= lenA; // Make sure first 6 bytes are also in if(TCPIsGetReady(sktHTTP) < (4 + 6) ) { lenA++; return HTTP_IO_NEED_DATA; } // Make sure it's an MPFS of the correct version lenA = TCPGetArray(sktHTTP, c, 10); curHTTP.byteCount -= lenA; if(memcmppgm2ram(c, (ROM void*)"\r\n\r\nMPFS\x02\x00", 10) == 0) {// Read as Ver 2.0 curHTTP.httpStatus = HTTP_MPFS_OK; // Format MPFS storage and put 6 byte tag curHTTP.file = MPFSFormat(); MPFSPutArray(curHTTP.file, &c[4], 6); } else {// Version is wrong curHTTP.httpStatus = HTTP_MPFS_ERROR; } } else {// Otherwise, remove as much as possible lenA = TCPGetArray(sktHTTP, NULL, TCPIsGetReady(sktHTTP) - 4); curHTTP.byteCount -= lenA; } break; // Received file is invalid case HTTP_MPFS_ERROR: curHTTP.byteCount -= TCPIsGetReady(sktHTTP); TCPDiscard(sktHTTP); if(curHTTP.byteCount < 100 || curHTTP.byteCount > 0x80000000) {// If almost all data was read, or if we overflowed, then return smHTTP = SM_HTTP_SERVE_HEADERS; return HTTP_IO_DONE; } break; // File is verified, so write the data case HTTP_MPFS_OK: // Determine how much to read lenA = TCPIsGetReady(sktHTTP); if(lenA > curHTTP.byteCount) lenA = curHTTP.byteCount; while(lenA > 0) { lenB = TCPGetArray(sktHTTP, c, mMIN(lenA,16)); curHTTP.byteCount -= lenB; lenA -= lenB; MPFSPutArray(curHTTP.file, c, lenB); } // If we've read all the data if(curHTTP.byteCount == 0) { MPFSPutEnd(); smHTTP = SM_HTTP_SERVE_HEADERS; return HTTP_IO_DONE; } } // Ask for more data return HTTP_IO_NEED_DATA; }
static BOOL PutFile(void) { BYTE v; switch(smFTPCommand) { case SM_FTP_CMD_IDLE: if ( !FTPFlags.Bits.bLoggedIn ) { FTPResponse = FTP_RESP_LOGIN; return TRUE; } else { FTPResponse = FTP_RESP_DATA_OPEN; FTPDataSocket = TCPConnect(&REMOTE_HOST(FTPSocket), FTPDataPort.Val); // Make sure that a valid socket was available and returned // If not, return with an error if(FTPDataSocket != INVALID_SOCKET) { smFTPCommand = SM_FTP_CMD_WAIT; } else { FTPResponse = FTP_RESP_DATA_NO_SOCKET; return TRUE; } } break; case SM_FTP_CMD_WAIT: if ( TCPIsConnected(FTPDataSocket) ) { #if defined(FTP_PUT_ENABLED) if ( !MPFSIsInUse() ) #endif { #if defined(FTP_PUT_ENABLED) FTPFileHandle = MPFSFormat(); #endif smFTPCommand = SM_FTP_CMD_RECEIVE; } } break; case SM_FTP_CMD_RECEIVE: if ( TCPIsGetReady(FTPDataSocket) ) { // Reload timeout timer. lastActivity = TickGet(); MPFSPutBegin(FTPFileHandle); while( TCPGet(FTPDataSocket, &v) ) { USARTPut(v); #if defined(FTP_PUT_ENABLED) MPFSPut(v); #endif } FTPFileHandle = MPFSPutEnd(); TCPDiscard(FTPDataSocket); // Print hash characters on FTP client display if(TCPIsPutReady(FTPSocket)) { TCPPut(FTPSocket, '#'); TCPFlush(FTPSocket); } } else if ( !TCPIsConnected(FTPDataSocket) ) { #if defined(FTP_PUT_ENABLED) MPFSPutEnd(); MPFSClose(); #endif TCPDisconnect(FTPDataSocket); FTPDataSocket = INVALID_SOCKET; FTPResponse = FTP_RESP_DATA_CLOSE; return TRUE; } } return FALSE; }
/********************************************************************* * Function: void FTPServer(void) * * PreCondition: FTPInit() must already be called. * * Input: None * * Output: Opened FTP connections are served. * * Side Effects: None * * Overview: * * Note: This function acts as a task (similar to one in * RTOS). This function performs its task in * co-operative manner. Main application must call * this function repeatdly to ensure all open * or new connections are served on time. ********************************************************************/ BOOL FTPServer(void) { BYTE v; TICK currentTick; if ( !TCPIsConnected(FTPSocket) ) { FTPStringLen = 0; FTPCommand = FTP_CMD_NONE; smFTP = SM_FTP_NOT_CONNECTED; FTPFlags.Val = 0; smFTPCommand = SM_FTP_CMD_IDLE; return TRUE; } if ( TCPIsGetReady(FTPSocket) ) { lastActivity = TickGet(); while( TCPGet(FTPSocket, &v ) ) { USARTPut(v); FTPString[FTPStringLen++] = v; if ( FTPStringLen == MAX_FTP_CMD_STRING_LEN ) FTPStringLen = 0; } TCPDiscard(FTPSocket); if ( v == '\n' ) { FTPString[FTPStringLen] = '\0'; FTPStringLen = 0; ParseFTPString(); FTPCommand = ParseFTPCommand(FTP_argv[0]); } } else if ( smFTP != SM_FTP_NOT_CONNECTED ) { currentTick = TickGet(); currentTick = TickGetDiff(currentTick, lastActivity); if ( currentTick >= FTP_TIMEOUT ) { lastActivity = TickGet(); FTPCommand = FTP_CMD_QUIT; smFTP = SM_FTP_CONNECTED; } } switch(smFTP) { case SM_FTP_NOT_CONNECTED: FTPResponse = FTP_RESP_BANNER; lastActivity = TickGet(); /* No break - Continue... */ case SM_FTP_RESPOND: SM_FTP_RESPOND_Label: if(!TCPIsPutReady(FTPSocket)) { return TRUE; } else { ROM char* pMsg; pMsg = FTPResponseString[FTPResponse]; while( (v = *pMsg++) ) { USARTPut(v); TCPPut(FTPSocket, v); } TCPFlush(FTPSocket); FTPResponse = FTP_RESP_NONE; smFTP = SM_FTP_CONNECTED; } // No break - this will speed up little bit case SM_FTP_CONNECTED: if ( FTPCommand != FTP_CMD_NONE ) { if ( ExecuteFTPCommand(FTPCommand) ) { if ( FTPResponse != FTP_RESP_NONE ) smFTP = SM_FTP_RESPOND; else if ( FTPCommand == FTP_CMD_QUIT ) smFTP = SM_FTP_NOT_CONNECTED; FTPCommand = FTP_CMD_NONE; smFTPCommand = SM_FTP_CMD_IDLE; } else if ( FTPResponse != FTP_RESP_NONE ) { smFTP = SM_FTP_RESPOND; goto SM_FTP_RESPOND_Label; } } break; } return TRUE; }
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 SMTP Client State machine(void) * * PreCondition: FTPInit() must already be called. * * Input: None * * Output: Ready to send mail. * * Side Effects: None * * Overview: * * Note: This function acts as a task (similar to one in * RTOS). This function performs its task in * co-operative manner. Main application must call * this function repeatedly to ensure it can send * mails when requested. (include in the main loop) ********************************************************************/ void SMTPClient(void) { BYTE v; // TICK currentTick; // check if state machine is stuck somewhere and reset the SM after a while if needed : if ((smSMTP != SM_SMTP_STDBY) && (TickGetDiff(TickGet(), lastActivity) > (15 * TICK_SECOND))) { if (TCPIsConnected(SMTPSocket)) TCPDisconnect(SMTPSocket) ; if(cptretry--) { // if not all retries done... lastActivity = TickGet(); // re-init delay smSMTP = SM_SMTP_STDBY ; // force standby state } else { fsend_mail = FALSE ; // give up ! smSMTP = SM_SMTP_STDBY ; // -> standby } } // work each state : switch(smSMTP) { case SM_SMTP_STDBY: // standby: idle, waiting for connection request if (fsend_mail) { if (TickGetDiff(TickGet(), lastActivity) > (10 * TICK_SECOND)) { USARTPut(0xBB) ; lastActivity = TickGet(); ARPResolve(&nodedist.IPAddr) ; // resolve IP adress smSMTP = SM_SMTP_ARP ; // -> wait ARP answer } } break ; case SM_SMTP_ARP: // wait ARP to be resolved if ( ARPIsResolved(&nodedist.IPAddr, &nodedist.MACAddr)) { SMTPSocket = TCPConnect(&nodedist, SMTP_PORT) ; if (SMTPSocket == INVALID_SOCKET) { fsend_mail = FALSE ; // avorte } else { smSMTP = SM_SMTP_CONNECT ; // -> attente ACK } } break ; case SM_SMTP_CONNECT: // standby: attente ack connexion if (TCPIsConnected(SMTPSocket)) { smSMTP = SM_SMTP_WELCOME ; // -> attente WELCOME } break ; case SM_SMTP_WELCOME: // attente welcome du serveur if (TCPIsGetReady(SMTPSocket)) { if (TCPGet(SMTPSocket, &v)) { if (v == '2') { // commence par un 2 ? (220..) TCPDiscard(SMTPSocket) ; ExecuteSMTPCommand(SMTP_CMD_HELO) ; smSMTP = SM_SMTP_HELO ; // -> attente reponse au HELO }else { smSMTP = SM_SMTP_DONE ; // -> disconnect } } } break ; case SM_SMTP_HELO: // attente HELO du serveur if (TCPIsGetReady(SMTPSocket)) { if (TCPGet(SMTPSocket,&v)) { if (v == '2') { // commence par un 2 ? (220..) TCPDiscard(SMTPSocket) ; ExecuteSMTPCommand(SMTP_CMD_FROM) ; smSMTP = SM_SMTP_FROM ; // -> attente reponse au FROM }else { smSMTP = SM_SMTP_DONE ; // -> disconnect } } } break ; case SM_SMTP_FROM: // attente HELO du serveur if (TCPIsGetReady(SMTPSocket)) { if (TCPGet(SMTPSocket,&v)) { if (v == '2') { // commence par un 2 ? (220..) TCPDiscard(SMTPSocket) ; ExecuteSMTPCommand(SMTP_CMD_TO) ; smSMTP = SM_SMTP_TO ; // -> attente reponse au TO }else { smSMTP = SM_SMTP_DONE ; // -> disconnect } } } break ; case SM_SMTP_TO: // attente HELO du serveur if (TCPIsGetReady(SMTPSocket)) { if (TCPGet(SMTPSocket,&v)) { if (v == '2') { // commence par un 2 ? (220..) TCPDiscard(SMTPSocket) ; ExecuteSMTPCommand(SMTP_CMD_DATA) ; smSMTP = SM_SMTP_DATA1 ; // -> attente reponse au DATA }else { smSMTP = SM_SMTP_DONE ; // -> disconnect } } } break ; case SM_SMTP_DATA1: // when OK send message headers if (TCPIsGetReady(SMTPSocket)) { if (TCPGet(SMTPSocket,&v)) { if (v == '3') { // commence par un 3 ? (220..) TCPDiscard(SMTPSocket) ; ExecuteSMTPCommand(SMTP_CMD_DATA_HEADERS) ; // send headers // ExecuteSMTPCommand(SMTP_CMD_DATA_MESSAGE) ; // message // ExecuteSMTPCommand(SMTP_CMD_DATA_END) ; // termine smSMTP = SM_SMTP_DATA2; // -> send body }else { smSMTP = SM_SMTP_DONE ; // -> disconnect } } } break ; case SM_SMTP_DATA2: // wait to send message body if (TCPIsPutReady(SMTPSocket)) { // wait for TX buffer free ExecuteSMTPCommand(SMTP_CMD_DATA_MESSAGE) ; // message smSMTP = SM_SMTP_DATA3 ; // -> attente reponse au TO } else { // USARTPut(0xCC) ; vérifié qu'il y avait bien besoin d'une attente ici } break ; case SM_SMTP_DATA3: // wait to send the final "." if (TCPIsPutReady(SMTPSocket)) { // wait for TX buffer free ExecuteSMTPCommand(SMTP_CMD_DATA_END) ; // termine smSMTP = SM_SMTP_QUIT ; // -> end } else { // USARTPut(0xDD) ; vérifié qu'il y avait bien besoin d'une attente ici } break ; case SM_SMTP_QUIT: // wait last message before leaving... if (TCPIsGetReady(SMTPSocket)) { if (TCPGet(SMTPSocket,&v)) { if (v == '2') { // commence par un 2 ? (220..) TCPDiscard(SMTPSocket) ; smSMTP = SM_SMTP_DONE ; // -> deconnecte }else { smSMTP = SM_SMTP_DONE ; // -> disconnect } } } break ; case SM_SMTP_DONE: // disconnect Socket : if (TCPIsConnected(SMTPSocket) && (TCPIsPutReady(SMTPSocket))) { // wait for TX buff free TCPDisconnect(SMTPSocket) ; } fsend_mail = FALSE ; // done ! smSMTP = SM_SMTP_STDBY ; // -> standby break ; } }
void lftp_task( void ) { WORD ttt; BYTE c; BOOL bPreLine; BOOL bPostLine; // Nothing to do if we don't have a link if ( !MACIsLinked() ) return; // check if state machine is stuck somewhere and reset the it after a while if needed : if ( ( ftp_state != LFTP_STATE_NONE ) && ( TickGetDiff( TickGet(), lastActivity) > ( LFTP_TIMEOUT * TICK_SECOND ) ) ) { // Close ftp client socker if open //if ( TCPIsConnected( ftpsocket ) ) { writeRomString2Socket( quit ); TCPDisconnect( ftpsocket ); ftpsocket = UNKNOWN_SOCKET; //} // Close data socket if open TCPDisconnect( datasocket ); datasocket = UNKNOWN_SOCKET; // Check if we should try again or if its time // to pack it in cntBeforeFail++; if ( cntBeforeFail > LFTP_MAX_RETRIES ) { cntBeforeFail = 0; ftp_state = LFTP_STATE_NONE; // Give up... bftpLoadWork = FALSE; // Work is done - failed } ftp_state = LFTP_STATE_NONE; } switch( ftp_state ) { // ** // Start to work if its time to do so case LFTP_STATE_NONE: // Check timer and see if we should fetch // data from the server. lastActivity = TickGet(); if ( bftpLoadWork ) { ftp_state = LFTP_STATE_ARP; // Must get MAC address for server cntBeforeFail = 0; // Init. failure counter DBG_OUT('A'); } break; //** // Resolve the MAC address of the ftp server case LFTP_STATE_ARP: ftp_nodeinfo.IPAddr.v[ 0 ] = LFTP_SERVER_IP_v0; ftp_nodeinfo.IPAddr.v[ 1 ] = LFTP_SERVER_IP_v1; ftp_nodeinfo.IPAddr.v[ 2 ] = LFTP_SERVER_IP_v2; ftp_nodeinfo.IPAddr.v[ 3 ] = LFTP_SERVER_IP_v3; if ( ARPIsTxReady() ) { DBG_OUT('B'); ARPResolve( &ftp_nodeinfo.IPAddr ); // resolve IP adress ftp_state = LFTP_STATE_ARP_RESOLVE; lastActivity = TickGet(); } break; // ** // Check if the ftp MAC address is resolved case LFTP_STATE_ARP_RESOLVE: if ( ARPIsResolved( &ftp_nodeinfo.IPAddr, &ftp_nodeinfo.MACAddr ) ) { DBG_OUT('D'); ftp_state = LFTP_STATE_CONNECT; lastActivity = TickGet(); } break; // ** // Connect to ftp server case LFTP_STATE_CONNECT: // Try to connect ftpsocket = TCPConnect( &ftp_nodeinfo, LFTP_PORT ); if ( INVALID_SOCKET != ftpsocket ) { DBG_OUT('E'); ftp_state = LFTP_STATE_CONNECT_WAIT; lastActivity = TickGet(); } break; // ** // Waiting for ftp connection case LFTP_STATE_CONNECT_WAIT: if ( TCPIsConnected( ftpsocket ) ) { DBG_OUT('F'); ftp_state = LFTP_STATE_USER; lastActivity = TickGet(); } break; // Here we wait for server connection and send // USER command if OK case LFTP_STATE_USER: // Fetch data if we are connected if ( TCPIsGetReady( ftpsocket ) ) { // get first digit while( TCPGet( ftpsocket, &c ) ) { if ( isdigit( c ) ) break; } // If connected with positive response "2xx - xxxxxxxx..." // we send username. If not we just timeout if ( '2' == c ) { DBG_OUT('G'); writeRomString2Socket( user ); ftp_state = LFTP_STATE_PASS; lastActivity = TickGet(); } TCPDiscard( ftpsocket ); } break; // ** // Here we wait for response from USER command // and send PASS command if OK case LFTP_STATE_PASS: // Fetch data if we are connected if ( TCPIsGetReady( ftpsocket ) ) { DBG_OUT('$'); // get first digit while( TCPGet( ftpsocket, &c ) ) { DBG_OUT(c); if ( isdigit( c ) ) break; } // If connected with positive response "3xx - xxxxxxxx..." // we send username. If not we just timeout if ( ('3' == c ) || ('2' == c ) ) { DBG_OUT('H'); writeRomString2Socket( pass ); ftp_state = LFTP_STATE_PASV; lastActivity = TickGet(); } TCPDiscard( ftpsocket ); } break; // ** // Here we wait for response of PASS command // and send PASV command if positive and also // creates the data socket case LFTP_STATE_PASV: // Fetch data if we are connected if ( TCPIsGetReady( ftpsocket ) ) { DBG_OUT('!'); // get first digit while( TCPGet( ftpsocket, &c ) ) { DBG_OUT(c); if ( isdigit( c ) ) break; } // If connected with positive response "2xx - xxxxxxxx..." // we send username. If not we just timeout if ( '2' == c ) { DBG_OUT('I'); writeRomString2Socket( pasv ); ftp_state = LFTP_STATE_RETR; lastActivity = TickGet(); } TCPDiscard( ftpsocket ); } break; // ** // Here we wait for the result of PASV command // and parse its data // if OK we send RETR and go on to the next state case LFTP_STATE_RETR: // Fetch data if we are connected if ( TCPIsGetReady( ftpsocket ) ) { TCPGet( ftpsocket, &c ); if ( '2' == c ) { DBG_OUT('J'); // Get pasv parameters getPasvParams(); // retrive file writeRomString2Socket( retr ); ttt = portdata; while ( ttt ) { DBG_OUT('0' + (ttt % 10) ); ttt = ttt / 10; } ftp_state = LFTP_STATE_DATA_CONNECT; } TCPDiscard( ftpsocket ); } break; // ** // Connect to the data socket case LFTP_STATE_DATA_CONNECT: // Try to connect datasocket = TCPConnect( &ftp_nodeinfo, portdata ); if ( INVALID_SOCKET != datasocket ) { DBG_OUT('K'); ftp_state = LFTP_STATE_WAIT_DATA_CONNECT; lastActivity = TickGet(); } break; // ** // Wait for the data connection to establish case LFTP_STATE_WAIT_DATA_CONNECT: if ( TCPIsConnected( datasocket ) ) { DBG_OUT('L'); //writeRomString2Socket( lftpDataSocket, crlf ); ftp_state = LFTP_STATE_FETCH_DATA; lastActivity = TickGet(); } // Check for reply on ftp socket FIX!!!! if ( TCPIsGetReady( ftpsocket ) ) { DBG_OUT('?'); while( TCPGet( ftpsocket, &c ) ) { DBG_OUT( c ); } TCPDiscard( ftpsocket ); } break; // ** // Fetch the data and send it out on the // serial i/f case LFTP_STATE_FETCH_DATA: // Fetch data if we are connected if ( TCPIsGetReady( datasocket ) ) { DBG_OUT('M'); // Framework start serPutByte( 0x00 ); serPutByte( 0xff ); serPutByte( 0xff ); serPutByte( 0x01 ); serPutByte( 0x01 ); serPutByte( 0x01 ); bPreLine = FALSE; bPostLine = FALSE; // get data while( TCPGet( datasocket, &c ) ) { if ( 0x0d == c ) { // We skip CR } else if ( 0x0a == c ) { // Send end line stuff serPutByte( 0xff ); bPreLine = FALSE; bPostLine = TRUE; } else { bPostLine = FALSE; // no end line codes sent if ( !bPreLine ) { // Send preline stuff bPreLine = TRUE; serPutByte( 0x01 ); serPutByte( 0x03 ); serPutByte( 0xef ); serPutByte( 0xb0 ); } serPutByte( c ); } } // If we end with a row without LF we must send // Line end stuff if ( !bPostLine ) { serPutByte( 0xff ); } // Framework end serPutByte( 0xff ); serPutByte( 0x00 ); ftp_state = LFTP_STATE_END; TCPDiscard( datasocket ); } // Check for data on ftp socket if ( TCPIsGetReady( ftpsocket ) ) { while( TCPGet( ftpsocket, &c ) ) { DBG_OUT( c ); } TCPDiscard( ftpsocket ); } break; // ** // We are done for this time case LFTP_STATE_END: DBG_OUT('*'); TCPDisconnect( ftpsocket ); TCPDisconnect( datasocket ); bftpLoadWork = FALSE; // Work is done ftp_state = LFTP_STATE_NONE; break; } }
/********************************************************************* * Function: void UART2TCPBridgeTask(void) * * PreCondition: Stack is initialized() * * Input: None * * Output: None * * Side Effects: None * * Overview: None * * Note: None ********************************************************************/ void UART2TCPBridgeTask2(void) { static enum _BridgeState { SM_HOME = 0, SM_SOCKET_OBTAINED } BridgeState = SM_HOME; static TCP_SOCKET MySocket = INVALID_SOCKET; WORD wMaxPut, wMaxGet; //, w; //BYTE *RXHeadPtrShadow, *RXTailPtrShadow; //BYTE *TXHeadPtrShadow, *TXTailPtrShadow; unsigned char buffer[PACK_MAX_RX_SIZE]; DATA_RX_PACKET_T * prx; DATA_TX_PACKET_T * ptx; switch(BridgeState) { default: case SM_HOME: putrsUART((ROM char*)"\r\n IN UART2TCPBridgeTask() home"); #if defined(USE_REMOTE_TCP_SERVER) // Connect a socket to the remote TCP server MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, UART1TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE); #else MySocket = TCPOpen(0, TCP_OPEN_SERVER, UART1TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE); #endif // Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available // If this ever happens, you need to go add one to TCPIPConfig.h if(MySocket == INVALID_SOCKET) break; // Eat the first TCPWasReset() response so we don't // infinitely create and reset/destroy client mode sockets TCPWasReset(MySocket); // We have a socket now, advance to the next state BridgeState = SM_SOCKET_OBTAINED; break; case SM_SOCKET_OBTAINED: //RELAY_OUT_1 = 0; // Reset all buffers if the connection was lost if(TCPWasReset(MySocket)) { // Optionally discard anything in the UART FIFOs //RXHeadPtr = vUARTRXFIFO; //RXTailPtr = vUARTRXFIFO; //TXHeadPtr = vUARTTXFIFO; //TXTailPtr = vUARTTXFIFO; // If we were a client socket, close the socket and attempt to reconnect #if defined(USE_REMOTE_TCP_SERVER) TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; BridgeState = SM_HOME; break; #endif } // Don't do anything if nobody is connected to us if(!TCPIsConnected(MySocket)) { LED7_IO = 0; break; } LED7_IO = 1; // Make sure to clear UART errors so they don't block all future operations if(OERR2) //RCSTAbits.OERR) { //RCSTAbits.CREN = 0; CREN2 = 0; //RCSTAbits.CREN = 1; CREN2 = 1; LED1_IO ^= 1; } if(FERR2) //RCSTAbits.FERR) { BYTE dummy = RCREG2; //RCREG; LED2_IO ^= 1; } prx = GetFinishedPacket(); if(prx != NULL) { if(prx->finished) { if(prx->index > 0) { wMaxPut = TCPIsPutReady(MySocket); // Get TCP TX FIFO space wMaxPut = (prx->index > wMaxPut)?wMaxPut:prx->index; if(wMaxPut > 0) { TCPPutArray(MySocket, &(prx->buffer[0]), wMaxPut); prx->index = 0; prx->finished = 0; TCPFlush(MySocket); } } prx->index = 0; prx->finished = 0; //测试用 //if(THISINFO)putrsUART((ROM char *)"\r\UART Bridge look at it"); } } //PIE1bits.RCIE = 1; RC2IE = 1; wMaxGet = TCPIsGetReady(MySocket); // Get TCP RX FIFO byte count if(wMaxGet > 0) { DATA_TX_PACKET_T * ptx = find_next_empty_tx_buffer(); if(ptx != NULL) { wMaxGet = (wMaxGet > PACK_MAX_RX_SIZE)?PACK_MAX_RX_SIZE:wMaxGet; TCPGetArray(MySocket,(BYTE *)&buffer[0],wMaxGet); ptx = prase_in_buffer(buffer,wMaxGet); if(ptx != NULL) { if(ptx->index > 0) { //启动发送 //PIE1bits.TXIE = 1; TX2IE = 1; } } } } else { TCPDiscard(MySocket); } break; } }
/// @cond debug //**************************************************************************** // TCPRxFlush callback function //**************************************************************************** int cTCPRxFlush() { TCPDiscard(xSocket); return 0; }
/* * Main entry point. */ void main(void) { static TICK8 t = 0; #ifdef HEATHERD NODE_INFO tcpServerNode; static TCP_SOCKET tcpSocketUser = INVALID_SOCKET; BYTE c; #endif static BYTE testLED; testLED = 1; //Set SWDTEN bit, this will enable the watch dog timer WDTCON_SWDTEN = 1; aliveCntrMain = 0xff; //Disable alive counter during initialization. Setting to 0xff disables it. //Initialize any application specific hardware. InitializeBoard(); //Initialize all stack related components. Following steps must //be performed for all applications using PICmicro TCP/IP Stack. TickInit(); //Initialize buses busInit(); //Initialize serial ports early, because they could be required for debugging if (appcfgGetc(APPCFG_USART1_CFG & APPCFG_USART_ENABLE)) { appcfgUSART(); //Configure the USART1 } if (appcfgGetc(APPCFG_USART2_CFG & APPCFG_USART_ENABLE)) { appcfgUSART2(); //Configure the USART2 } //After initializing all modules that use interrupts, enable global interrupts INTCON_GIEH = 1; INTCON_GIEL = 1; //Initialize file system. fsysInit(); //Intialize HTTP Execution unit htpexecInit(); //Initialize Stack and application related NV variables. appcfgInit(); //First call appcfgCpuIOValues() and then only appcfgCpuIO()!!! This ensures the value are set, before enabling ports. appcfgCpuIOValues(); //Configure the CPU's I/O port pin default values appcfgCpuIO(); //Configure the CPU's I/O port pin directions - input or output appcfgADC(); //Configure ADC unit appcfgPWM(); //Configure PWM Channels //Serial configuration menu - display it for configured time and allow user to enter configuration menu scfInit(appcfgGetc(APPCFG_STARTUP_SER_DLY)); //LCD Display Initialize lcdInit(); //Initialize expansion board appcfgXboard(); StackInit(); #if defined(STACK_USE_HTTP_SERVER) HTTPInit(); #endif #if defined(STACK_USE_FTP_SERVER) FTPInit(); #endif //Intialise network componet of buses - only call after StackInit()! busNetInit(); //Initializes events. evtInit(); //Initializes "UDP Command Port" and "UDP Even Port". cmdInit(); ioInit(); #if (DEBUG_MAIN >= LOG_DEBUG) debugPutMsg(1); //@mxd:1:Starting main loop #endif /* * Once all items are initialized, go into infinite loop and let * stack items execute their tasks. * If application needs to perform its own task, it should be * done at the end of while loop. * Note that this is a "co-operative mult-tasking" mechanism * where every task performs its tasks (whether all in one shot * or part of it) and returns so that other tasks can do their * job. * If a task needs very long time to do its job, it must broken * down into smaller pieces so that other tasks can have CPU time. */ #ifdef HEATHERD //Create a TCP socket that listens on port 54123 tcpSocketUser = TCPListen(HEATHERD); #define HEATHERD_ENABLE (!(appcfgGetc(APPCFG_TRISA) & 1)) #define HEATHERD_WRITE_ENABLE (!(appcfgGetc(APPCFG_TRISA) & 2)) #endif while(1) { aliveCntrMain = 38; //Reset if not services in 52.42ms x 38 = 2 seconds //Blink SYSTEM LED every second. if (appcfgGetc(APPCFG_SYSFLAGS) & APPCFG_SYSFLAGS_BLINKB6) { //Configure RB6 as output, and blink it every 500ms if ( TickGetDiff8bit(t) >= ((TICK8)TICKS_PER_SECOND / (TICK8)2) ) { t = TickGet8bit(); //If B6 is configured as input, change to output if (appcfgGetc(APPCFG_TRISB) & 0x40) { appcfgPutc(APPCFG_TRISB, appcfgGetc(APPCFG_TRISB) & 0b10111111); } TRISB_RB6 = 0; LATB6 ^= 1; //Toggle //Toggle IOR5E LED, if IOR5E is present if (appcfgGetc(APPCFG_XBRD_TYPE) == XBRD_TYPE_IOR5E) { ior5eLatchData.bits.ledPWR ^= 1; // Toggle } } } //This task performs normal stack task including checking for incoming packet, //type of packet and calling appropriate stack entity to process it. StackTask(); //Service LCD display lcdService(); //Process commands cmdTask(); //Process events evtTask(); //Process serial busses busTask(); //I2C Task i2cTask(); #ifdef HEATHERD //Has a remote node made connection with the port we are listening on if ((tcpSocketUser != INVALID_SOCKET) && TCPIsConnected(tcpSocketUser)) { if (HEATHERD_ENABLE) { //Is there any data waiting for us on the TCP socket? //Because of the design of the Modtronix TCP/IP stack we have to //consume all data sent to us as soon as we detect it. while(TCPIsGetReady(tcpSocketUser)) { //We are only interrested in the first byte of the message. TCPGet(tcpSocketUser, &c); if (HEATHERD_WRITE_ENABLE) serPutByte(c); } //Discard the socket buffer. TCPDiscard(tcpSocketUser); while (serIsGetReady() && TCPIsPutReady(tcpSocketUser)) { TCPPut(tcpSocketUser,serGetByte()); } TCPFlush(tcpSocketUser); } else { TCPDisconnect(tcpSocketUser); } } #endif #if defined(STACK_USE_HTTP_SERVER) //This is a TCP application. It listens to TCP port 80 //with one or more sockets and responds to remote requests. HTTPServer(); #endif #if defined(STACK_USE_FTP_SERVER) FTPServer(); #endif #if defined(STACK_USE_ANNOUNCE) DiscoveryTask(); #endif #if defined(STACK_USE_NBNS) NBNSTask(); #endif //Add your application speicifc tasks here. ProcessIO(); //For DHCP information, display how many times we have renewed the IP //configuration since last reset. if ( DHCPBindCount != myDHCPBindCount ) { #if (DEBUG_MAIN >= LOG_INFO) debugPutMsg(2); //@mxd:2:DHCP Bind Count = %D debugPutByteHex(DHCPBindCount); #endif //Display new IP address #if (DEBUG_MAIN >= LOG_INFO) debugPutMsg(3); //@mxd:3:DHCP complete, IP = %D.%D.%D.%D debugPutByteHex(AppConfig.MyIPAddr.v[0]); debugPutByteHex(AppConfig.MyIPAddr.v[1]); debugPutByteHex(AppConfig.MyIPAddr.v[2]); debugPutByteHex(AppConfig.MyIPAddr.v[3]); #endif myDHCPBindCount = DHCPBindCount; #if defined(STACK_USE_ANNOUNCE) AnnounceIP(); #endif } } }
/*** void TCPSocket::discardReadBuffer(void) ** ** Synopsis: ** Empties (flushes) the input (read) buffer. ** All bytes are discarded. ** ** Parameters: ** None ** ** Return Values: ** None ** ** Errors: ** None ** ** Notes: ** ** This call is safe to make without checking the connection status. ** */ void TCPSocket::discardReadBuffer(void) { TCPDiscard(&_socket); }
/********************************************************************* * Serve a single connection ********************************************************************/ static void HTTP_Process(BOOL available) { BYTE error; const struct HTTP_FileContent rom *content; retry: switch(HTTP.StateMachine) { // Introduced explicit disconnect state handling in order to properly // finish all queries case SM_HTTP_IDLE: // Connections closed for any reason will automatically end up in // the disconnected state, so this is a good place to make sure // we don't leak files. if(HTTP.file) { FSfclose(HTTP.file); HTTP.file = NULL; } // Just wait for any connection to be made if(!TCPIsConnected(HTTP.socket)) // Don't break for new connections. There may be // an entire request in the buffer already. return; HTTP.StateMachine = SM_HTTP_PARSE_REQUEST; // Adjust the TCP FIFOs for optimal reception of // the next HTTP request from the browser ///while(!TCPAdjustFIFOSize(HTTP.socket, 1, 0, TCP_ADJUST_PRESERVE_RX | TCP_ADJUST_GIVE_REST_TO_RX)); // Fallthrough // . // . // . case SM_HTTP_PARSE_REQUEST: // Verify the entire first line is in the FIFO and if(!HTTP_SetBuf(-1)) break; // Check that the file system is mounted error = HTTP_ERR_NOT_AVAILABLE; if(available) { // Parse the request line error = HTTP_ERR_NOT_IMPLEMENTED; // Parses the first line for a file name and GET args if(HTTP_Parse()) { static char read[] = FS_READ; error = HTTP_ERR_NOT_FOUND; // Open the file if(HTTP.file = FSfopen(HTTP_ParseName, read), HTTP.file) // Success! goto retry; } } HTTP.FileType = error; HTTP.StateMachine = SM_HTTP_ERROR; // Fallthrough // . // . // . case SM_HTTP_ERROR: if(TCPIsPutReady(HTTP.socket) >= strlenpgm((const char far rom *) HTTP_Errors[HTTP.FileType])) { TCPPutROMString(HTTP.socket, (ROM BYTE *) HTTP_Errors[HTTP.FileType]); TCPFlush(HTTP.socket); TCPDisconnect(HTTP.socket); HTTP.StateMachine = SM_HTTP_IDLE; } break; // Parse out the POST header lines case SM_HTTP_POST_HEADER: // Is the next line ready yet? while(HTTP_SetBuf(-1)) { char ch; // Isolate the field name HTTP_Buffer.write = HTTP_Data; do { ch = HTTP_GetBuf(); // The payload starts after the first empty line if(ch == '\0') { HTTP.StateMachine = SM_HTTP_POST_ARGUMENTS; goto retry; } HTTP_PutBuf(ch); } while(ch != ' '); HTTP_PutBuf('\0'); // The content length is needed to know the length of the variable block if(!Cfg_StringCompare(HTTP_Data, (const char ROM *) HTTP_CONTENT_LENGTH_STRING)) { unsigned int len = 0; while(ch = HTTP_GetBuf() - '0', (unsigned char) ch <= 9) { len *= 10; len += ch; } HTTP.length = len; } } break; case SM_HTTP_POST_ARGUMENTS: if(!HTTP_SetBuf(HTTP.length)) break; if(HTTP_ParseAttribs()) { Microchip_RefreshSettings(); Microchip_RestoreSPI(); }; HTTP.StateMachine = SM_HTTP_PARSE_HEADERS; // Fallthrough // . // . // . case SM_HTTP_PARSE_HEADERS: content = &HTTP_FileContent[HTTP.FileType]; // Write response string TCPPutROMString(HTTP.socket, HTTP_OK_STRING); TCPPutROMString(HTTP.socket, (ROM BYTE *) content->mime); // Generic cache control mechanism TCPPutROMString(HTTP.socket, content->cache ? HTTP_NL_DO_CACHE_STRING : HTTP_NL_NO_CACHE_STRING); // Generate the content-length field so that dismount errors can be detected HTTP.dynamic = content->dynamic; if(!HTTP.dynamic) { Numeric(Num_Buffer, HTTP.file->size); TCPPutROMString(HTTP.socket, HTTP_NL_CONTENT_LENGTH_STRING); TCPPutString(HTTP.socket, (BYTE *) Num_Buffer); } TCPPutROMString(HTTP.socket, HTTP_NL_HEADER_END_STRING); HTTP.StateMachine = SM_HTTP_PROCESS_GET; // Fallthrough // . // . // . case SM_HTTP_PROCESS_GET: // Throw away any more data receieved - we aren't going to use it. TCPDiscard(HTTP.socket); if(HTTP_SendFile()) { TCPFlush(HTTP.socket); TCPDisconnect(HTTP.socket); HTTP.StateMachine = SM_HTTP_IDLE; } break; } // Flush out any remaining line-buffered data HTTP_FlushBuf(); // If, during handling of HTTP socket, it gets disconnected then forget // about any previous processing and return to the idle state. // // Do wait until as much processing as possible has been completed on // whatever data remains in the buffers however if(!TCPIsConnected(HTTP.socket)) HTTP.StateMachine = SM_HTTP_IDLE; }