/***************************************************************************** Function: int connect( SOCKET s, struct sockaddr* name, int namelen ) Summary: This function connects to the peer communications end point. Description: The connect function assigns the address of the peer communications endpoint. For stream sockets, connection is established between the endpoints. For datagram sockets, an address filter is established between the endpoints until changed with another connect() function. Precondition: socket function should be called. Parameters: s - Socket descriptor returned from a previous call to socket. name - pointer to the sockaddr structure containing the peer address and port number. namelen - length of the sockaddr structure. Returns: If the connect() function succeeds, it returns 0. Otherwise, the value SOCKET_ERROR is returned to indicate an error condition. For stream based socket, if the connection is not established yet, connect returns SOCKET_CNXN_IN_PROGRESS. Remarks: None. ***************************************************************************/ int connect( SOCKET s, struct sockaddr* name, int namelen ) { struct BSDSocket *socket; struct sockaddr_in *addr; DWORD remoteIP; WORD remotePort; WORD localPort; if( s >= BSD_SOCKET_COUNT ) return SOCKET_ERROR; socket = &BSDSocketArray[s]; if( socket->bsdState < SKT_CREATED ) return SOCKET_ERROR; if( (unsigned int)namelen < sizeof(struct sockaddr_in)) return SOCKET_ERROR; addr = (struct sockaddr_in *)name; remotePort = addr->sin_port; remoteIP = addr->sin_addr.S_un.S_addr; if( remoteIP == 0u || remotePort == 0u ) return SOCKET_ERROR; if( socket->SocketType == SOCK_STREAM ) { switch(socket->bsdState) { case SKT_EST: return 0; // already established case SKT_IN_PROGRESS: if(HandlePossibleTCPDisconnection(s)) return SOCKET_ERROR; if(!TCPIsConnected(socket->SocketID)) return SOCKET_CNXN_IN_PROGRESS; socket->bsdState = SKT_EST; return 0; //success case SKT_CREATED: case SKT_BOUND: socket->SocketID = TCPOpen(remoteIP, TCP_OPEN_IP_ADDRESS, remotePort, TCP_PURPOSE_BERKELEY_CLIENT); if(socket->SocketID == INVALID_SOCKET) return SOCKET_ERROR; // Clear the first reset flag TCPWasReset(socket->SocketID); socket->isServer = FALSE; socket->bsdState = SKT_IN_PROGRESS; return SOCKET_CNXN_IN_PROGRESS; default: return SOCKET_ERROR; } } else { // If not explicitly bound to a local port, implicitly do the binding if(socket->bsdState == SKT_CREATED) { localPort = gAutoPortNumber++; if(gAutoPortNumber > 5000u) // reset the port numbers gAutoPortNumber = 1024; //socket->SocketID = UDPOpen(localPort, NULL, remotePort); socket->SocketID = UDPOpenEx(0,UDP_OPEN_SERVER,localPort, remotePort); if(socket->SocketID == INVALID_UDP_SOCKET) return SOCKET_ERROR; socket->bsdState = SKT_BOUND; } if(socket->bsdState != SKT_BOUND) return SOCKET_ERROR; // UDP: remote port is used as a filter. Need to call connect when using // send/recv calls. No need to call 'connect' if using sendto/recvfrom // calls. socket->remotePort = remotePort; socket->remoteIP = remoteIP; return 0; //success } return SOCKET_ERROR; }
/********************************************************************* * 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; } }
/**************************************************************************** Function: void DDNSTask(void) Summary: Dynamic DNS client task/state machine. Description: This function performs the background tasks of the Dynamic DNS Client. Once the DDNSPointers structure is configured, this task attempt to update the Dynamic DNS hostname on a periodic schedule. The task first accesses the CheckIP server to determine the device's current external IP address. If the IP address has changed, it issues an update command to the dynamic DNS service to propagate the change. This sequence executes whenever dwUpdateAt elapses, which by default is every 10 minutes, or when an update is forced. Precondition: DDNSInit() has been called. Parameters: None Returns: None Remarks: This function acts as a task (similar to one in an RTOS). It performs its task in a co-operative manner, and the main application must call this function periodically to ensure that its tasks get executed in a timely fashion. ***************************************************************************/ void DDNSTask(void) { BYTE i; static TICK Timer; static TCP_SOCKET MySocket = INVALID_SOCKET; static char ROM * ROMStrPtr; static char * RAMStrPtr; static BYTE vBuffer[16]; WORD wPos; static IP_ADDR ipParsed; static enum { SM_IDLE = 0u, SM_BEGIN_CHECKIP, //0x1 SM_CHECKIP_SKT_OBTAINED, //0x2 SM_CHECKIP_FIND_DELIMITER, //0x3 SM_CHECKIP_FIND_ADDRESS, //0x4 SM_CHECKIP_DISCONNECT, //0x5 SM_IP_UPDATE_HOME, //0x6 SM_IP_UPDATE_SKT_OBTAINED, //0x7 /* HTTP request msg is divided into 6 parts SM_IP_UPDATE_REQ_A,B,C,D,E,F as the tcp ip tx buffer is only able to carry 200 bytes at a time. */ SM_IP_UPDATE_REQ_A, //0x8 SM_IP_UPDATE_REQ_B, //0x9 SM_IP_UPDATE_REQ_C, //0xa SM_IP_UPDATE_REQ_D, //0xb SM_IP_UPDATE_REQ_E, //0xc SM_IP_UPDATE_REQ_F, //0xd SM_IPUPDATE_FIND_RESPONSE, //0xe SM_IPUPDATE_PARSE_RESPONSE, //0xf SM_IPUDATE_DISCONNECT, //0x10 SM_DONE, // Done, try again in 10 minutes SM_SOFT_ERROR, // Soft error, try again in 30 seconds SM_SYSTEM_ERROR // System error, try again in 30 minutes } smDDNS = SM_IDLE; switch(smDDNS) { case SM_IDLE: // Wait for timeout to begin IP check if((LONG)(TickGet() - dwUpdateAt) < 0) break; // Otherwise, continue to next state smDDNS = SM_BEGIN_CHECKIP; case SM_BEGIN_CHECKIP: // If a fatal error has occurred, abort to the SM_DONE state and keep // the error message. if(lastStatus >= DDNS_STATUS_ABUSE && lastStatus <= DDNS_STATUS_911) { smDDNS = SM_DONE; break; } // If DDNSClient is not properly configured, abort if( // Verify that each pointer is not null, and is not empty (DDNSClient.ROMPointers.Host && (!DDNSClient.Host.szROM || *DDNSClient.Host.szROM == '\0') ) || (!DDNSClient.ROMPointers.Host && (!DDNSClient.Host.szRAM || *DDNSClient.Host.szRAM == '\0') ) || (DDNSClient.ROMPointers.Username && (!DDNSClient.Username.szROM || *DDNSClient.Username.szROM == '\0') ) || (!DDNSClient.ROMPointers.Username && (!DDNSClient.Username.szRAM || *DDNSClient.Username.szRAM == '\0') ) || (DDNSClient.ROMPointers.Password && (!DDNSClient.Password.szROM || *DDNSClient.Password.szROM == '\0') ) || (!DDNSClient.ROMPointers.Password && (!DDNSClient.Password.szRAM || *DDNSClient.Password.szRAM == '\0') ) || (DDNSClient.ROMPointers.CheckIPServer && (!DDNSClient.CheckIPServer.szROM || *DDNSClient.CheckIPServer.szROM == '\0') ) || (!DDNSClient.ROMPointers.CheckIPServer && (!DDNSClient.CheckIPServer.szRAM || *DDNSClient.CheckIPServer.szRAM == '\0') ) || (DDNSClient.ROMPointers.UpdateServer && (!DDNSClient.UpdateServer.szROM || *DDNSClient.UpdateServer.szROM == '\0') ) || (!DDNSClient.ROMPointers.UpdateServer && (!DDNSClient.UpdateServer.szRAM || *DDNSClient.UpdateServer.szRAM == '\0') ) ) { smDDNS = SM_SOFT_ERROR; lastStatus = DDNS_STATUS_INVALID; break; } // Start with an invalidated IP String vBuffer[0] = '\0'; // Connect a socket to the remote server if(DDNSClient.ROMPointers.CheckIPServer) { MySocket = TCPOpen((DWORD)(ROM_PTR_BASE)DDNSClient.CheckIPServer.szROM, TCP_OPEN_ROM_HOST, DDNSClient.CheckIPPort, TCP_PURPOSE_DEFAULT); } else { MySocket = TCPOpen((DWORD)(PTR_BASE)DDNSClient.CheckIPServer.szRAM, TCP_OPEN_RAM_HOST, DDNSClient.CheckIPPort, TCP_PURPOSE_DEFAULT); } // If no socket available, try again on next loop if(MySocket == INVALID_SOCKET) break; smDDNS++; Timer = TickGet(); break; case SM_CHECKIP_SKT_OBTAINED: // Wait for the remote server to accept our connection request if(!TCPIsConnected(MySocket)) { // Time out if too much time is spent in this state if(TickGet()-Timer > 6*TICK_SECOND) { // Close the socket so it can be used by other modules // We will retry soon TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; lastStatus = DDNS_STATUS_CHECKIP_ERROR; smDDNS = SM_SOFT_ERROR; } break; } Timer = TickGet(); // Make certain the socket can be written to if(TCPIsPutReady(MySocket) < 125)//125 = size of TCP Tx buffer break; // Transmit the request to the server TCPPutROMString(MySocket, (ROM BYTE*)"GET / HTTP/1.0\r\nHost: "); if(DDNSClient.ROMPointers.CheckIPServer) { TCPPutROMString(MySocket, DDNSClient.CheckIPServer.szROM); } else { TCPPutString(MySocket, DDNSClient.CheckIPServer.szRAM); } TCPPutROMString(MySocket, (ROM BYTE*)"\r\nConnection: close\r\n\r\n"); // Send the packet TCPFlush(MySocket); smDDNS++; break; case SM_CHECKIP_FIND_DELIMITER: // Check if remote node is still connected. If not, force to the disconnect state, // but don't break because data may still be waiting. if(!TCPIsConnected(MySocket) || TickGet() - Timer > 6*TICK_SECOND) smDDNS = SM_CHECKIP_DISCONNECT; // Search out the "Address: " delimiter in the response wPos = TCPFindROMArray(MySocket, (ROM BYTE*)"Address: ", 9, 0, FALSE); // If not yet found, clear as much as possible and break if(wPos == 0xffff) { wPos = TCPIsGetReady(MySocket); if(wPos > 9) TCPGetArray(MySocket, NULL, wPos - 9); break; } // Clear up to and past that string TCPGetArray(MySocket, NULL, wPos + 9); // Continue on to read the IP Timer = TickGet(); smDDNS++; case SM_CHECKIP_FIND_ADDRESS: // Check if remote node is still connected. If not, force to the disconnect state, // but don't break because data may still be waiting. if(!TCPIsConnected(MySocket) || TickGet() - Timer > 6*TICK_SECOND) smDDNS = SM_CHECKIP_DISCONNECT; // Search out the "</body>" delimiter in the response wPos = TCPFindROMArray(MySocket, (ROM BYTE*)"</body>", 7, 0, FALSE); // If not yet found, break if(wPos == 0xffff) break; // Read and terminate that string as the IP address (preventing buffer overflows) if(wPos > 15) wPos = 15; TCPGetArray(MySocket, vBuffer, wPos); vBuffer[wPos] = '\0'; // Parse the IP address that was read, invalidating on failure if(!StringToIPAddress(vBuffer, &ipParsed)) vBuffer[0] = '\0'; // Continue on to close the socket case SM_CHECKIP_DISCONNECT: // Close the socket TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; // Determine if an update is necessary if(vBuffer[0] == '\0') {// CheckIP Failed lastStatus = DDNS_STATUS_CHECKIP_ERROR; smDDNS = SM_SOFT_ERROR; break; } if( (ipParsed.Val ==lastKnownIP.Val) && (!bForceUpdate)) { // IP address has not changed and no update is forced lastStatus = DDNS_STATUS_UNCHANGED; smDDNS = SM_DONE; break; } // Need to perform an update lastKnownIP = ipParsed; bForceUpdate = FALSE; smDDNS++; break; case SM_IP_UPDATE_HOME: // Connect a socket to the remote server if(DDNSClient.ROMPointers.UpdateServer) { MySocket = TCPOpen((DWORD)(ROM_PTR_BASE)DDNSClient.UpdateServer.szROM, TCP_OPEN_ROM_HOST, DDNSClient.UpdatePort, TCP_PURPOSE_DEFAULT); } else { MySocket = TCPOpen((DWORD)(PTR_BASE)DDNSClient.UpdateServer.szRAM, TCP_OPEN_RAM_HOST, DDNSClient.UpdatePort, TCP_PURPOSE_DEFAULT); } // If no socket is available, try again on the next loop if(MySocket == INVALID_SOCKET) break; // Move on to the next state smDDNS++; Timer = TickGet(); break; case SM_IP_UPDATE_SKT_OBTAINED: // Wait for the remote server to accept our connection request if(!TCPIsConnected(MySocket)) { // Time out if too much time is spent in this state if(TickGet() - Timer > 6*TICK_SECOND) { // Close the socket so it can be used by other modules // We will try again immediately TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; lastStatus = DDNS_STATUS_UPDATE_ERROR; smDDNS--; } break; } // Reset timer and begin sending the request Timer = TickGet(); smDDNS++; // No break needed...try to send first bit immediately. case SM_IP_UPDATE_REQ_A: // Check for lost connections or timeouts if(!TCPIsConnected(MySocket) || (TickGet() - Timer > 10*TICK_SECOND)) { lastStatus = DDNS_STATUS_UPDATE_ERROR; smDDNS = SM_IPUDATE_DISCONNECT; break; } if(TCPIsPutReady(MySocket) < 25u) // 25 =~ 16+9 break; TCPPutROMString(MySocket, (ROM BYTE*)"GET /nic/update?hostname="); smDDNS++; // No break needed...try to send next bit immediately. case SM_IP_UPDATE_REQ_B: // Check for lost connections or timeouts if(!TCPIsConnected(MySocket) || (TickGet() - Timer > 10*TICK_SECOND)) { lastStatus = DDNS_STATUS_UPDATE_ERROR; smDDNS = SM_IPUDATE_DISCONNECT; break; } // Try to write, verifying that space is available first if(DDNSClient.ROMPointers.Host) { if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)DDNSClient.Host.szROM)) break; TCPPutROMString(MySocket,DDNSClient.Host.szROM); } else { if(TCPIsPutReady(MySocket) < strlen((char*)DDNSClient.Host.szRAM)) break; TCPPutString(MySocket,DDNSClient.Host.szRAM); } smDDNS++; // No break needed...try to send next bit immediately. case SM_IP_UPDATE_REQ_C: // Check for lost connections or timeouts if(!TCPIsConnected(MySocket) || TickGet() - Timer > 10*TICK_SECOND) { lastStatus = DDNS_STATUS_UPDATE_ERROR; smDDNS = SM_IPUDATE_DISCONNECT; break; } if(TCPIsPutReady(MySocket) < 70u) break; TCPPutROMString(MySocket, (ROM BYTE*)"&myip="); TCPPutString(MySocket, vBuffer); TCPPutROMString(MySocket, (ROM BYTE*)"&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG HTTP/1.0"); TCPFlush(MySocket); smDDNS++; // No break needed...try to send next bit immediately. case SM_IP_UPDATE_REQ_D: // Check for lost connections or timeouts if(!TCPIsConnected(MySocket) || TickGet() - Timer > 10*TICK_SECOND) { lastStatus = DDNS_STATUS_UPDATE_ERROR; smDDNS = SM_IPUDATE_DISCONNECT; break; } if(TCPIsPutReady(MySocket) < 131u) // 131 =~ 8+23 + dynamic dns server hostname break; TCPPutROMString(MySocket, (ROM BYTE*)"\r\nHost: ");//8 if(DDNSClient.ROMPointers.UpdateServer) TCPPutROMString(MySocket,DDNSClient.UpdateServer.szROM); else TCPPutString(MySocket,DDNSClient.UpdateServer.szRAM); TCPPutROMString(MySocket, (ROM BYTE*)"\r\nAuthorization: Basic ");//23 TCPFlush(MySocket); smDDNS++; // No break needed...try to send the next bit immediately. case SM_IP_UPDATE_REQ_E: // Check for lost connections or timeouts if(!TCPIsConnected(MySocket) || TickGet() - Timer > 6*TICK_SECOND) { lastStatus = DDNS_STATUS_UPDATE_ERROR; smDDNS = SM_IPUDATE_DISCONNECT; break; } // User name and passwords for DynDNS.org can each be up to 24 characters // Base64 encoded data is always at least 25% bigger than the original if(TCPIsPutReady(MySocket) < 100u) break; if(DDNSClient.ROMPointers.Username) { ROMStrPtr = (ROM char*)DDNSClient.Username.szROM; wPos = strlenpgm(ROMStrPtr); } else { RAMStrPtr = (char*)DDNSClient.Username.szRAM; wPos = strlen((char*)RAMStrPtr); } i = 0; while(wPos) { while(i < wPos && i < 3u) { if(DDNSClient.ROMPointers.Username) vBuffer[i] = *ROMStrPtr++; else vBuffer[i] = *RAMStrPtr++; i++; } wPos -= i; if(i == 3u) { Base64Encode(vBuffer, i, vBuffer, 4); TCPPutArray(MySocket, vBuffer, 4); i = 0; } } if(DDNSClient.ROMPointers.Password) { ROMStrPtr = (ROM char*)DDNSClient.Password.szROM; wPos = strlenpgm(ROMStrPtr); } else { RAMStrPtr = (char*)DDNSClient.Password.szRAM; wPos = strlen((char*)RAMStrPtr); } // Increment for the ':' separator and i for bytes left in username wPos += i + 1; vBuffer[i++] = ':'; while(wPos) { while(i < wPos && i < 3u) { if(DDNSClient.ROMPointers.Password) vBuffer[i] = *ROMStrPtr++; else vBuffer[i] = *RAMStrPtr++; i++; } wPos -= i; Base64Encode(vBuffer, i, vBuffer, 4); TCPPutArray(MySocket, vBuffer, 4); i = 0; } TCPFlush(MySocket); smDDNS++; break; case SM_IP_UPDATE_REQ_F: // Check for lost connections or timeouts if(!TCPIsConnected(MySocket) || TickGet() - Timer > 10*TICK_SECOND) { lastStatus = DDNS_STATUS_UPDATE_ERROR; smDDNS = SM_IPUDATE_DISCONNECT; break; } if(TCPIsPutReady(MySocket) < 50) break; TCPPutROMString(MySocket, (ROM BYTE*)"\r\nUser-Agent: Microchip - TCPIPSTACK - "VERSION"\r\n\r\n"); TCPFlush(MySocket); smDDNS++; // Reset the timer to wait for a response Timer = TickGet(); break; case SM_IPUPDATE_FIND_RESPONSE: // Locate the response string // Wait up to 10 seconds for a response if(TickGet() - Timer > 10*TICK_SECOND) { lastStatus = DDNS_STATUS_UPDATE_ERROR; smDDNS = SM_IPUDATE_DISCONNECT; break; } // According to HTTP, the response will start after the two CRLFs wPos = TCPFindROMArray(MySocket, (ROM BYTE*)"\r\n\r\n", 4, 0, FALSE); // If not yet found, eliminate everything up to if(wPos == 0xffff) { wPos = TCPIsGetReady(MySocket); if(wPos > 4) TCPGetArray(MySocket, NULL, wPos - 4); break; } TCPGetArray(MySocket, NULL, wPos+4); smDDNS++; // No break...continue to next state immediately case SM_IPUPDATE_PARSE_RESPONSE: // Try to parse the response text // Wait up to 10 seconds for the remote server to disconnect // so we know all data has been received if(TCPIsConnected(MySocket) && TickGet() - Timer < 10*TICK_SECOND) break; // Read the response code wPos = TCPIsGetReady(MySocket); if(wPos > sizeof(vBuffer) - 1) wPos = sizeof(vBuffer) - 1; wPos = TCPGetArray(MySocket, vBuffer, wPos); vBuffer[wPos] = '\0'; for(i = 0; i < sizeof(vBuffer); i++) if(vBuffer[i] == ' ') vBuffer[i] = '\0'; for(lastStatus = 0; lastStatus <= DDNS_STATUS_UPDATE_ERROR; lastStatus++) if(!strcmppgm2ram((char*)vBuffer, (ROM char*)_updateIpSrvrResponse[lastStatus])) break; smDDNS++; // No break...continue to finalization case SM_IPUDATE_DISCONNECT: // Close the socket so it can be used by other modules. if(MySocket != INVALID_SOCKET) { TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; } // Determine what to do based on status if(lastStatus <= DDNS_STATUS_NUMHOST || lastStatus == DDNS_STATUS_UNCHANGED) smDDNS = SM_DONE; else if(lastStatus == DDNS_STATUS_911 || lastStatus == DDNS_STATUS_DNSERR) smDDNS = SM_SYSTEM_ERROR; else smDDNS = SM_SOFT_ERROR; smDDNS++; break; case SM_DONE: dwUpdateAt = TickGet() + 10*60*TICK_SECOND; // 10 minutes smDDNS = SM_IDLE; break; case SM_SOFT_ERROR: dwUpdateAt = TickGet() + 30*TICK_SECOND; // 30 seconds smDDNS = SM_IDLE; break; case SM_SYSTEM_ERROR: dwUpdateAt = TickGet() + 30*60*TICK_SECOND; // 30 minutes smDDNS = SM_IDLE; break; } }
void twatchTasks(char frameAdvance){ //this state machine services the #twatch static enum _twatchState { TWATCH_INIT=0, TWATCH_IDLE, TWATCH_TRENDS_TCP_START, TWATCH_TRENDS_TCP_SOCKET_OBTAINED, TWATCH_TRENDS_TCP_PROCESS_RESPONSE, TWATCH_TRENDS_TCP_DISCONNECT, TWATCH_SEARCH_TCP_START, TWATCH_SEARCH_TCP_SOCKET_OBTAINED, TWATCH_SEARCH_TCP_PROCESS_RESPONSE, TWATCH_SEARCH_TCP_DISCONNECT, } twatchState = TWATCH_INIT; //massive twitter parsing state machine static enum _HTTPstatus { UNKNOWN=0, OK, ERROR, } HTTPstatus = UNKNOWN; //get and track HTTP status and handle errors static unsigned char HTTPheaderBuf[20]; //used to store HTTP headers static unsigned char HTTPheaderBufCnt; //pointer static BYTE refreshFeeds=0, HTTPretry=0, URLencode[]="%20";//extra static vars for twitter parser BYTE i,k; WORD w; BYTE vBuffer[51]; BYTE cnt; static TICK Timer; static TCP_SOCKET MySocket = INVALID_SOCKET; if(frameAdvance==1) refreshFeeds++; //counts the minutes switch(twatchState) { case TWATCH_INIT: trendParser.success=0; //clear these flag on first run searchParser.success=0;//display IP address and info until valid connection twatchState=TWATCH_TRENDS_TCP_START; //start TCP data grabber next cycle break; case TWATCH_IDLE: //if this variable set, then start the refresh process if(refreshFeeds>TWATCH_REFRESH_INTERVAL){ //if it has been at least 5 minutes, get new trends and tweet search results refreshFeeds=0; HTTPretry=0; //reset the number of retries twatchState=TWATCH_TRENDS_TCP_START; //start TCP data grabber next cycle } break; case TWATCH_TRENDS_TCP_START: //connect to twitter server MySocket = TCPOpen((DWORD)&ServerName[0], TCP_OPEN_RAM_HOST, ServerPort, TCP_PURPOSE_GENERIC_TCP_CLIENT); if(MySocket == INVALID_SOCKET) break; //abort if error, try again next time trendParser.updatingData=1; //updating data flag (probably not used anywhere) displayMode=UPDATE; //next LCD refresh will draw the update screen and then idle twatchState=TWATCH_TRENDS_TCP_SOCKET_OBTAINED; Timer = TickGet(); break; case TWATCH_TRENDS_TCP_SOCKET_OBTAINED: // Wait for the remote server to accept our connection request if(!TCPIsConnected(MySocket)) { // Time out if too much time is spent in this state if(TickGet()-Timer > 5*TICK_SECOND) { // Close the socket so it can be used by other modules TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; twatchState--; } break; } Timer = TickGet(); if(TCPIsPutReady(MySocket) < 125u) break; //if socket error, break and wait //form our trending topics JSON datafeed request TCPPutROMString(MySocket, (ROM BYTE*)"GET "); TCPPutROMString(MySocket, TrendURL); //use the trend URL TCPPutROMString(MySocket, (ROM BYTE*)" HTTP/1.0\r\nHost: "); TCPPutString(MySocket, ServerName); TCPPutROMString(MySocket, (ROM BYTE*)"\r\nConnection: close\r\n\r\n"); TCPFlush(MySocket); //send HTTP request to Twitter //setup/clear the parser struct trendParser.bufWritePointer=0; trendParser.foundTag=0; trendParser.tagCharMatchCnt=0; trendParser.tagTotalCnt=0; trendParser.bufWritePointer=0; searchParser.bufWritePointer=0;//reset the tweet buffer write pointer searchParser.term=0; //reset the number of terns in the tweet search parser structure for(i=0; i<MAX_TREND_TERMS; i++) searchParser.bufValueEndPosition[i]=0;//reset all buffer positions to 0 HTTPstatus = UNKNOWN; //reset the http status checker HTTPheaderBufCnt=0; //status checker buffer counter twatchState=TWATCH_TRENDS_TCP_PROCESS_RESPONSE; //next time process any incoming data break; case TWATCH_TRENDS_TCP_PROCESS_RESPONSE: if(!TCPIsConnected(MySocket)) twatchState = TWATCH_TRENDS_TCP_DISCONNECT; //check if we're still connected // Do not break; We might still have data in the TCP RX FIFO waiting for us w = TCPIsGetReady(MySocket);//how many bytes waiting? //process the server reply i = sizeof(vBuffer)-1; vBuffer[i] = '\0'; while(w){ if(w < i){ i = w; vBuffer[i] = '\0'; } w -= TCPGetArray(MySocket, vBuffer, i); for(cnt=0;cnt<i;cnt++){ //---------------// switch(HTTPstatus){ //check the first few bytes for HTTP/1.1 200 OK case UNKNOWN: //cache until a line break, then check header for response code before extracting tags HTTPheaderBuf[HTTPheaderBufCnt]=vBuffer[cnt];//add to the headerbuf array if(HTTPheaderBufCnt<19) HTTPheaderBufCnt++; //if it won't overrun the array, increment the counter if(vBuffer[cnt]==0x0d){//if current character is a line break, examine the header for the response code //is it HTTP? if(HTTPheaderBuf[0]=='H' && HTTPheaderBuf[1]=='T' && HTTPheaderBuf[2]=='T' && HTTPheaderBuf[3]=='P' ){ //loop past /1.x and space HTTPheaderBufCnt=4; while(HTTPheaderBuf[HTTPheaderBufCnt]!=' '){ HTTPheaderBufCnt++; if(HTTPheaderBufCnt>19) break; //buffer overrun } HTTPheaderBufCnt++; //is it 200? (should be a ASCII->int loop that gets the actual value for error handling.... check for overrun if( (HTTPheaderBufCnt <=17 ) && HTTPheaderBuf[HTTPheaderBufCnt]=='2' && HTTPheaderBuf[HTTPheaderBufCnt+1]=='0' && HTTPheaderBuf[HTTPheaderBufCnt+2]=='0'){ HTTPstatus=OK;//200 OK }else{ HTTPstatus=ERROR; //other status, error } } } break; case OK: //HTTP is OK, process the byte procTrend(vBuffer[cnt]); //json parsing state maching break; case ERROR://do nothing because we need to clear the buffer break; } //------------------// }//for loop if(twatchState == TWATCH_TRENDS_TCP_PROCESS_RESPONSE) break; }//while break; case TWATCH_TRENDS_TCP_DISCONNECT: TCPDisconnect(MySocket); //close the socket MySocket = INVALID_SOCKET; //did not get valid HTML, retry, got no tags, retry if(HTTPstatus!=OK || trendParser.tagTotalCnt==0 ){ HTTPretry++; if(HTTPretry>HTTP_MAX_RETRY){//retry 3 times, then wait a minute.... twatchState = TWATCH_IDLE; LCD_CursorPosition(21); //display waiting error LCD_WriteString("*Error, waiting 5min"); break; } LCD_CursorPosition(21); //display retry error LCD_WriteString("*Error, reconnecting"); twatchState = TWATCH_TRENDS_TCP_START; break; } HTTPretry=0; addToTrendBuffer(' ');//add trailing space trendParser.updatingData=0; //data update complete, clear update flag if(trendParser.success==0){ //if this is the first time throuigh, set the success flag trendParser.success=1; //set success flag, used to identify the very first successful xfer and clear IP address screen LCD_refresh(); //clear IP, show update screen } displayMode=NEWSCROLL;//start scrolling the terms, tweets will show when available in the parser struct twatchState = TWATCH_SEARCH_TCP_START; //will start searching on each term next time. searchParser.term set to 0 above... break; case TWATCH_SEARCH_TCP_START: //begins searching for recent tweets for each trending term //don't continue if there's no more term, an error, or overrun if(searchParser.term>=trendParser.tagTotalCnt || searchParser.term>=MAX_TREND_TERMS ){//don't continue if there's no more terms left to search twatchState = TWATCH_IDLE; //go back to idle break; } //skip if 0 length term if(trendParser.bufValueStartPosition[searchParser.term]==trendParser.bufValueEndPosition[searchParser.term]) { searchParser.term++; //increment to next trend term twatchState = TWATCH_SEARCH_TCP_START; //try again with the next trend term break; } //connect to twitter MySocket = TCPOpen((DWORD)&ServerName[0], TCP_OPEN_RAM_HOST, ServerPort, TCP_PURPOSE_GENERIC_TCP_CLIENT); if(MySocket == INVALID_SOCKET) break; //abort on error twatchState=TWATCH_SEARCH_TCP_SOCKET_OBTAINED; Timer = TickGet(); break; case TWATCH_SEARCH_TCP_SOCKET_OBTAINED: // Wait for the remote server to accept our connection request if(!TCPIsConnected(MySocket)){ // Time out if too much time is spent in this state if(TickGet()-Timer > 5*TICK_SECOND){ // Close the socket so it can be used by other modules TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; twatchState--; //searchParser.term++; //increment to next trend term, don't get stuck in loop //should add retries } break; } Timer = TickGet(); if(TCPIsPutReady(MySocket) < 125u) break; //socket ready for writes? TCPPutROMString(MySocket, (ROM BYTE*)"GET "); //setup the HTTP GET request TCPPutROMString(MySocket, SearchURL); //JSON search datafeed URL #ifndef JSON_DEBUG //add the search term to the JSON search URL. Requires urlencoding i=trendParser.bufValueStartPosition[searchParser.term]; //get the starting position of the term in the trend term buffer k=trendParser.bufValueEndPosition[searchParser.term]-1; //end position is one less because of auto increment //add each character of the trend term to the search URL while((i<k) && i<TREND_PARSER_BUFFER ){ //append each byte to the URL until the end position //URLencode anything not a-zA-Z0-9 -_.!~*'() if(URLencodeChar(trendParser.buf[i], &URLencode[0])==0){ TCPPut(MySocket, trendParser.buf[i]); //no URLencode required; }else{ TCPPutString(MySocket, URLencode); //use the URLencoded character now in URLencode array } i++; } #endif //form the rest of the HTTP request TCPPutROMString(MySocket, (ROM BYTE*)" HTTP/1.0\r\nHost: "); TCPPutString(MySocket, ServerName); TCPPutROMString(MySocket, (ROM BYTE*)"\r\nConnection: close\r\n\r\n"); TCPFlush(MySocket); //send the HTTP request to the Twitter server //setup the search parser struct searchParser.foundTag=0; searchParser.tagCharMatchCnt=0; searchParser.tagTotalCnt=0; searchParser.escape=0; HTTPstatus = UNKNOWN; //clear the HTTP status checker HTTPheaderBufCnt=0; addToSearchBuffer(0xff); //add beginning block to the text twatchState=TWATCH_SEARCH_TCP_PROCESS_RESPONSE; break; case TWATCH_SEARCH_TCP_PROCESS_RESPONSE: if(!TCPIsConnected(MySocket)) twatchState = TWATCH_SEARCH_TCP_DISCONNECT; //check for connection // Do not break; We might still have data in the TCP RX FIFO waiting for us w = TCPIsGetReady(MySocket); //how many bytes waiting? i = sizeof(vBuffer)-1; vBuffer[i] = '\0'; //add trailing 0 to array. while(w){ //process server reply if(w < i){ i = w; vBuffer[i] = '\0'; } w -= TCPGetArray(MySocket, vBuffer, i); for(cnt=0;cnt<i;cnt++){ //---------------// switch(HTTPstatus){ case UNKNOWN: //check header for response code before extracting tags HTTPheaderBuf[HTTPheaderBufCnt]=vBuffer[cnt];//add to the headerbuf array if(HTTPheaderBufCnt<19) HTTPheaderBufCnt++; //if it won't overrun the array, increment the counter if(vBuffer[cnt]==0x0d){//current character is a line break, examine the header for the response code //is it HTTP? if(HTTPheaderBuf[0]=='H' && HTTPheaderBuf[1]=='T' && HTTPheaderBuf[2]=='T' && HTTPheaderBuf[3]=='P' ){ //loop past /1.x and space HTTPheaderBufCnt=4; while(HTTPheaderBuf[HTTPheaderBufCnt]!=' '){ HTTPheaderBufCnt++; if(HTTPheaderBufCnt>19) break; //buffer overrun } HTTPheaderBufCnt++; //is it 200? (should be a ASCII->int loop that gets the actual value for error handling.... if( ((HTTPheaderBufCnt+2) < 20) && HTTPheaderBuf[HTTPheaderBufCnt]=='2' && HTTPheaderBuf[HTTPheaderBufCnt+1]=='0' && HTTPheaderBuf[HTTPheaderBufCnt+2]=='0'){ HTTPstatus=OK; }else{ HTTPstatus=ERROR; } } } break; case OK: procSearch(vBuffer[cnt]); break; case ERROR://do nothing because we need to clear the buffer break; } //------------------// }//for loop if(twatchState == TWATCH_SEARCH_TCP_PROCESS_RESPONSE) break; }//while break; case TWATCH_SEARCH_TCP_DISCONNECT: TCPDisconnect(MySocket); //close the socket MySocket = INVALID_SOCKET; //did not get valid HTML, retry, got no tags, retry once if no tags if(HTTPstatus!=OK ){ HTTPretry++; if(HTTPretry>HTTP_MAX_RETRY){//retry, then wait till next time... twatchState = TWATCH_IDLE; break; } twatchState = TWATCH_SEARCH_TCP_START; break; } HTTPretry=0; //success, clear number or retries //repeat for each trend term searchParser.success=1; searchParser.term++; twatchState = TWATCH_SEARCH_TCP_START; break; }//switch }//function
/***************************************************************************** Function: void SMTPTask(void) Summary: Performs any pending SMTP client tasks Description: This function handles periodic tasks associated with the SMTP client, such as processing initial connections and command sequences. Precondition: None Parameters: None Returns: None Remarks: This function acts as a task (similar to one in an RTOS). It performs its task in a co-operative manner, and the main application must call this function repeatedly to ensure that all open or new connections are served in a timely fashion. ***************************************************************************/ void SMTPTask(void) { BYTE i; WORD w; BYTE vBase64Buffer[4]; static DWORD Timer; static BYTE RXBuffer[4]; static ROM BYTE *ROMStrPtr, *ROMStrPtr2; static BYTE *RAMStrPtr; static WORD wAddressLength; WORD tmp; switch(TransportState) { case TRANSPORT_HOME: // SMTPBeginUsage() is the only function which will kick // the state machine into the next state break; case TRANSPORT_BEGIN: // Wait for the user to program all the pointers and then // call SMTPSendMail() if(!SMTPFlags.bits.ReadyToStart) break; // Obtain ownership of the DNS resolution module if(!DNSBeginUsage()) break; // Obtain the IP address associated with the SMTP mail server if(SMTPClient.Server.szRAM || SMTPClient.Server.szROM) { if(SMTPClient.ROMPointers.Server) DNSResolveROM(SMTPClient.Server.szROM, DNS_TYPE_A); else DNSResolve(SMTPClient.Server.szRAM, DNS_TYPE_A); } else { // If we don't have a mail server, try to send the mail // directly to the destination SMTP server if(SMTPClient.To.szRAM && !SMTPClient.ROMPointers.To) { SMTPClient.Server.szRAM = (BYTE*)strchr((char*)SMTPClient.To.szRAM, '@'); SMTPClient.ROMPointers.Server = 0; } else if(SMTPClient.To.szROM && SMTPClient.ROMPointers.To) { SMTPClient.Server.szROM = (ROM BYTE*)strchrpgm((ROM char*)SMTPClient.To.szROM, '@'); SMTPClient.ROMPointers.Server = 1; } if(!(SMTPClient.Server.szRAM || SMTPClient.Server.szROM)) { if(SMTPClient.CC.szRAM && !SMTPClient.ROMPointers.CC) { SMTPClient.Server.szRAM = (BYTE*)strchr((char*)SMTPClient.CC.szRAM, '@'); SMTPClient.ROMPointers.Server = 0; } else if(SMTPClient.CC.szROM && SMTPClient.ROMPointers.CC) { SMTPClient.Server.szROM = (ROM BYTE*)strchrpgm((ROM char*)SMTPClient.CC.szROM, '@'); SMTPClient.ROMPointers.Server = 1; } } if(!(SMTPClient.Server.szRAM || SMTPClient.Server.szROM)) { if(SMTPClient.BCC.szRAM && !SMTPClient.ROMPointers.BCC) { SMTPClient.Server.szRAM = (BYTE*)strchr((char*)SMTPClient.BCC.szRAM, '@'); SMTPClient.ROMPointers.Server = 0; } else if(SMTPClient.BCC.szROM && SMTPClient.ROMPointers.BCC) { SMTPClient.Server.szROM = (ROM BYTE*)strchrpgm((ROM char*)SMTPClient.BCC.szROM, '@'); SMTPClient.ROMPointers.Server = 1; } } // See if we found a hostname anywhere which we could resolve if(!(SMTPClient.Server.szRAM || SMTPClient.Server.szROM)) { DNSEndUsage(); ResponseCode = SMTP_RESOLVE_ERROR; TransportState = TRANSPORT_HOME; break; } // Skip over the @ sign and resolve the host name if(SMTPClient.ROMPointers.Server) { SMTPClient.Server.szROM++; DNSResolveROM(SMTPClient.Server.szROM, DNS_TYPE_MX); } else { SMTPClient.Server.szRAM++; DNSResolve(SMTPClient.Server.szRAM, DNS_TYPE_MX); } } Timer = TickGet(); TransportState++; break; case TRANSPORT_NAME_RESOLVE: // Wait for the DNS server to return the requested IP address if(!DNSIsResolved(&SMTPServer)) { // Timeout after 6 seconds of unsuccessful DNS resolution if(TickGet() - Timer > 6*TICK_SECOND) { ResponseCode = SMTP_RESOLVE_ERROR; TransportState = TRANSPORT_HOME; DNSEndUsage(); } break; } // Release the DNS module, we no longer need it if(!DNSEndUsage()) { // An invalid IP address was returned from the DNS // server. Quit and fail permanantly if host is not valid. ResponseCode = SMTP_RESOLVE_ERROR; TransportState = TRANSPORT_HOME; break; } TransportState++; // No need to break here case TRANSPORT_OBTAIN_SOCKET: // Connect a TCP socket to the remote SMTP server MySocket = TCPOpen(SMTPServer.Val, TCP_OPEN_IP_ADDRESS, SMTPClient.ServerPort, TCP_PURPOSE_DEFAULT); // Abort operation if no TCP sockets are available // If this ever happens, add some more // TCP_PURPOSE_DEFAULT sockets in TCPIPConfig.h if(MySocket == INVALID_SOCKET) break; TransportState++; Timer = TickGet(); // No break; fall into TRANSPORT_SOCKET_OBTAINED #if defined(STACK_USE_SSL_CLIENT) case TRANSPORT_SECURING_SOCKET: if(!TCPIsConnected(MySocket)) { // Don't stick around in the wrong state if the // server was connected, but then disconnected us. // Also time out if we can't establish the connection // to the SMTP server if((LONG)(TickGet()-Timer) > (LONG)(SMTP_SERVER_REPLY_TIMEOUT)) { ResponseCode = SMTP_CONNECT_ERROR; TransportState = TRANSPORT_CLOSE; } break; } SMTPFlags.bits.ConnectedOnce = TRUE; // Start SSL if needed for this connection if(SMTPClient.UseSSL && !TCPStartSSLClient(MySocket,NULL)) break; // Move on to main state Timer = TickGet(); TransportState++; break; #endif case TRANSPORT_SOCKET_OBTAINED: if(!TCPIsConnected(MySocket)) { // Don't stick around in the wrong state if the // server was connected, but then disconnected us. // Also time out if we can't establish the connection // to the SMTP server if(SMTPFlags.bits.ConnectedOnce || ((LONG)(TickGet()-Timer) > (LONG)(SMTP_SERVER_REPLY_TIMEOUT))) { ResponseCode = SMTP_CONNECT_ERROR; TransportState = TRANSPORT_CLOSE; } break; } SMTPFlags.bits.ConnectedOnce = TRUE; #if defined(STACK_USE_SSL_CLIENT) // Make sure the SSL handshake has completed if(SMTPClient.UseSSL && TCPSSLIsHandshaking(MySocket)) break; #endif // See if the server sent us anything while(TCPIsGetReady(MySocket)) { TCPGet(MySocket, &i); switch(RXParserState) { case RX_BYTE_0: case RX_BYTE_1: case RX_BYTE_2: RXBuffer[RXParserState] = i; RXParserState++; break; case RX_BYTE_3: switch(i) { case ' ': SMTPFlags.bits.RXSkipResponse = FALSE; RXParserState++; break; case '-': SMTPFlags.bits.RXSkipResponse = TRUE; RXParserState++; break; case '\r': RXParserState = RX_SEEK_LF; break; } break; case RX_SEEK_CR: if(i == '\r') RXParserState++; break; case RX_SEEK_LF: // If we received the whole command if(i == '\n') { RXParserState = RX_BYTE_0; if(!SMTPFlags.bits.RXSkipResponse) { // The server sent us a response code // Null terminate the ASCII reponse code so we can convert it to an integer RXBuffer[3] = 0; ResponseCode = atoi((char*)RXBuffer); // Handle the response switch(SMTPState) { case SMTP_HELO_ACK: if(ResponseCode >= 200u && ResponseCode <= 299u) { if(SMTPClient.Username.szRAM || SMTPClient.Username.szROM) SMTPState = SMTP_AUTH_LOGIN; else SMTPState = SMTP_MAILFROM; } else SMTPState = SMTP_QUIT_INIT; break; case SMTP_AUTH_LOGIN_ACK: case SMTP_AUTH_USERNAME_ACK: if(ResponseCode == 334u) SMTPState++; else SMTPState = SMTP_QUIT_INIT; break; case SMTP_AUTH_PASSWORD_ACK: if(ResponseCode == 235u) SMTPState++; else SMTPState = SMTP_QUIT_INIT; break; case SMTP_HOME: case SMTP_MAILFROM_ACK: case SMTP_RCPTTO_ACK: case SMTP_RCPTTOCC_ACK: case SMTP_RCPTTOBCC_ACK: tmp = SMTPState; if(ResponseCode >= 200u && ResponseCode <= 299u) SMTPState++; else SMTPState = SMTP_QUIT_INIT; break; case SMTP_DATA_ACK: if(ResponseCode == 354u) SMTPState++; else SMTPState = SMTP_QUIT_INIT; break; case SMTP_DATA_BODY_ACK: if(ResponseCode >= 200u && ResponseCode <= 299u) SMTPFlags.bits.SentSuccessfully = TRUE; SMTPState = SMTP_QUIT_INIT; break; // Default case needed to supress compiler diagnostics default: break; } } } else if(i != '\r') RXParserState--; break; } } // Generate new data in the TX buffer, as needed, if possible if(TCPIsPutReady(MySocket) < 64u) break; switch(SMTPState) { case SMTP_HELO: if(SMTPClient.Username.szROM == NULL) TCPPutROMString(MySocket, (ROM BYTE*)"HELO MCHPBOARD\r\n"); else TCPPutROMString(MySocket, (ROM BYTE*)"EHLO MCHPBOARD\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_AUTH_LOGIN: // Note: This state is only entered from SMTP_HELO_ACK if the application // has specified a Username to use (either SMTPClient.Username.szROM or // SMTPClient.Username.szRAM is non-NULL) TCPPutROMString(MySocket, (ROM BYTE*)"AUTH LOGIN\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_AUTH_USERNAME: // Base 64 encode and transmit the username. if(SMTPClient.ROMPointers.Username) { ROMStrPtr = SMTPClient.Username.szROM; w = strlenpgm((ROM char*)ROMStrPtr); } else { RAMStrPtr = SMTPClient.Username.szRAM; w = strlen((char*)RAMStrPtr); } while(w) { i = 0; while((i < w) && (i < sizeof(vBase64Buffer)*3/4)) { if(SMTPClient.ROMPointers.Username) vBase64Buffer[i] = *ROMStrPtr++; else vBase64Buffer[i] = *RAMStrPtr++; i++; } w -= i; Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer)); TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer)); } TCPPutROMString(MySocket, (ROM BYTE*)"\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_AUTH_PASSWORD: // Base 64 encode and transmit the password if(SMTPClient.ROMPointers.Password) { ROMStrPtr = SMTPClient.Password.szROM; w = strlenpgm((ROM char*)ROMStrPtr); } else { RAMStrPtr = SMTPClient.Password.szRAM; w = strlen((char*)RAMStrPtr); } while(w) { i = 0; while((i < w) && (i < sizeof(vBase64Buffer)*3/4)) { if(SMTPClient.ROMPointers.Password) vBase64Buffer[i] = *ROMStrPtr++; else vBase64Buffer[i] = *RAMStrPtr++; i++; } w -= i; Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer)); TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer)); } TCPPutROMString(MySocket, (ROM BYTE*)"\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_MAILFROM: // Send MAIL FROM header. Note that this is for the SMTP server validation, // not what actually will be displayed in the recipients mail client as a // return address. TCPPutROMString(MySocket, (ROM BYTE*)"MAIL FROM:<"); if(SMTPClient.ROMPointers.From) { ROMStrPtr = FindROMEmailAddress(SMTPClient.From.szROM, &wAddressLength); TCPPutROMArray(MySocket, ROMStrPtr, wAddressLength); } else { RAMStrPtr = FindEmailAddress(SMTPClient.From.szRAM, &wAddressLength); TCPPutArray(MySocket, RAMStrPtr, wAddressLength); } TCPPutROMString(MySocket, (ROM BYTE*)">\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_RCPTTO_INIT: // See if there are any (To) recipients to process if(SMTPClient.To.szRAM && !SMTPClient.ROMPointers.To) { RAMStrPtr = FindEmailAddress(SMTPClient.To.szRAM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTO; break; } } if(SMTPClient.To.szROM && SMTPClient.ROMPointers.To) { ROMStrPtr = FindROMEmailAddress(SMTPClient.To.szROM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTO; break; } } SMTPState = SMTP_RCPTTOCC_INIT; break; case SMTP_RCPTTO: case SMTP_RCPTTOCC: case SMTP_RCPTTOBCC: TCPPutROMString(MySocket, (ROM BYTE*)"RCPT TO:<"); if( (SMTPClient.ROMPointers.To && (SMTPState == SMTP_RCPTTO)) || (SMTPClient.ROMPointers.CC && (SMTPState == SMTP_RCPTTOCC)) || (SMTPClient.ROMPointers.BCC && (SMTPState == SMTP_RCPTTOBCC)) ) TCPPutROMArray(MySocket, ROMStrPtr, wAddressLength); else TCPPutArray(MySocket, RAMStrPtr, wAddressLength); TCPPutROMString(MySocket, (ROM BYTE*)">\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_RCPTTO_ISDONE: // See if we have any more (To) recipients to process // If we do, we must roll back a couple of states if(SMTPClient.ROMPointers.To) ROMStrPtr = FindROMEmailAddress(ROMStrPtr+wAddressLength, &wAddressLength); else RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTO; break; } // All done with To field SMTPState++; //No break case SMTP_RCPTTOCC_INIT: // See if there are any Carbon Copy (CC) recipients to process if(SMTPClient.CC.szRAM && !SMTPClient.ROMPointers.CC) { RAMStrPtr = FindEmailAddress(SMTPClient.CC.szRAM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOCC; break; } } if(SMTPClient.CC.szROM && SMTPClient.ROMPointers.CC) { ROMStrPtr = FindROMEmailAddress(SMTPClient.CC.szROM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOCC; break; } } SMTPState = SMTP_RCPTTOBCC_INIT; break; case SMTP_RCPTTOCC_ISDONE: // See if we have any more Carbon Copy (CC) recipients to process // If we do, we must roll back a couple of states if(SMTPClient.ROMPointers.CC) ROMStrPtr = FindROMEmailAddress(ROMStrPtr+wAddressLength, &wAddressLength); else RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOCC; break; } // All done with CC field SMTPState++; //No break case SMTP_RCPTTOBCC_INIT: // See if there are any Blind Carbon Copy (BCC) recipients to process if(SMTPClient.BCC.szRAM && !SMTPClient.ROMPointers.BCC) { RAMStrPtr = FindEmailAddress(SMTPClient.BCC.szRAM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOBCC; break; } } if(SMTPClient.BCC.szROM && SMTPClient.ROMPointers.BCC) { ROMStrPtr = FindROMEmailAddress(SMTPClient.BCC.szROM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOBCC; break; } } // All done with BCC field SMTPState = SMTP_DATA; break; case SMTP_RCPTTOBCC_ISDONE: // See if we have any more Blind Carbon Copy (CC) recipients to process // If we do, we must roll back a couple of states if(SMTPClient.ROMPointers.BCC) ROMStrPtr = FindROMEmailAddress(ROMStrPtr+wAddressLength, &wAddressLength); else RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOBCC; break; } // All done with BCC field SMTPState++; //No break case SMTP_DATA: TCPPutROMString(MySocket, (ROM BYTE*)"DATA\r\n"); SMTPState++; PutHeadersState = PUTHEADERS_FROM_INIT; TCPFlush(MySocket); break; case SMTP_DATA_HEADER: while((PutHeadersState != PUTHEADERS_DONE) && (TCPIsPutReady(MySocket) > 64u)) { switch(PutHeadersState) { case PUTHEADERS_FROM_INIT: if(SMTPClient.From.szRAM || SMTPClient.From.szROM) { PutHeadersState = PUTHEADERS_FROM; TCPPutROMString(MySocket, (ROM BYTE*)"From: "); } else { PutHeadersState = PUTHEADERS_TO_INIT; } break; case PUTHEADERS_FROM: if(SMTPClient.ROMPointers.From) { SMTPClient.From.szROM = TCPPutROMString(MySocket, SMTPClient.From.szROM); if(*SMTPClient.From.szROM == 0u) PutHeadersState = PUTHEADERS_TO_INIT; } else { SMTPClient.From.szRAM = TCPPutString(MySocket, SMTPClient.From.szRAM); if(*SMTPClient.From.szRAM == 0u) PutHeadersState = PUTHEADERS_TO_INIT; } break; case PUTHEADERS_TO_INIT: if(SMTPClient.To.szRAM || SMTPClient.To.szROM) { PutHeadersState = PUTHEADERS_TO; TCPPutROMString(MySocket, (ROM BYTE*)"\r\nTo: "); } else { PutHeadersState = PUTHEADERS_CC_INIT; } break; case PUTHEADERS_TO: if(SMTPClient.ROMPointers.To) { SMTPClient.To.szROM = TCPPutROMString(MySocket, SMTPClient.To.szROM); if(*SMTPClient.To.szROM == 0u) PutHeadersState = PUTHEADERS_CC_INIT; } else { SMTPClient.To.szRAM = TCPPutString(MySocket, SMTPClient.To.szRAM); if(*SMTPClient.To.szRAM == 0u) PutHeadersState = PUTHEADERS_CC_INIT; } break; case PUTHEADERS_CC_INIT: if(SMTPClient.CC.szRAM || SMTPClient.CC.szROM) { PutHeadersState = PUTHEADERS_CC; TCPPutROMString(MySocket, (ROM BYTE*)"\r\nCC: "); } else { PutHeadersState = PUTHEADERS_SUBJECT_INIT; } break; case PUTHEADERS_CC: if(SMTPClient.ROMPointers.CC) { SMTPClient.CC.szROM = TCPPutROMString(MySocket, SMTPClient.CC.szROM); if(*SMTPClient.CC.szROM == 0u) PutHeadersState = PUTHEADERS_SUBJECT_INIT; } else { SMTPClient.CC.szRAM = TCPPutString(MySocket, SMTPClient.CC.szRAM); if(*SMTPClient.CC.szRAM == 0u) PutHeadersState = PUTHEADERS_SUBJECT_INIT; } break; case PUTHEADERS_SUBJECT_INIT: if(SMTPClient.Subject.szRAM || SMTPClient.Subject.szROM) { PutHeadersState = PUTHEADERS_SUBJECT; TCPPutROMString(MySocket, (ROM BYTE*)"\r\nSubject: "); } else { PutHeadersState = PUTHEADERS_OTHER_INIT; } break; case PUTHEADERS_SUBJECT: if(SMTPClient.ROMPointers.Subject) { SMTPClient.Subject.szROM = TCPPutROMString(MySocket, SMTPClient.Subject.szROM); if(*SMTPClient.Subject.szROM == 0u) PutHeadersState = PUTHEADERS_OTHER_INIT; } else { SMTPClient.Subject.szRAM = TCPPutString(MySocket, SMTPClient.Subject.szRAM); if(*SMTPClient.Subject.szRAM == 0u) PutHeadersState = PUTHEADERS_OTHER_INIT; } break; case PUTHEADERS_OTHER_INIT: TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2); if(SMTPClient.OtherHeaders.szRAM || SMTPClient.OtherHeaders.szROM) { PutHeadersState = PUTHEADERS_OTHER; } else { TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2); PutHeadersState = PUTHEADERS_DONE; SMTPState++; } break; case PUTHEADERS_OTHER: if(SMTPClient.ROMPointers.OtherHeaders) { SMTPClient.OtherHeaders.szROM = TCPPutROMString(MySocket, SMTPClient.OtherHeaders.szROM); if(*SMTPClient.OtherHeaders.szROM == 0u) { TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2); PutHeadersState = PUTHEADERS_DONE; SMTPState++; } } else { SMTPClient.OtherHeaders.szRAM = TCPPutString(MySocket, SMTPClient.OtherHeaders.szRAM); if(*SMTPClient.OtherHeaders.szRAM == 0u) { TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2); PutHeadersState = PUTHEADERS_DONE; SMTPState++; } } break; // Default case needed to supress compiler diagnostics default: break; } } TCPFlush(MySocket); break; case SMTP_DATA_BODY_INIT: SMTPState++; RAMStrPtr = SMTPClient.Body.szRAM; ROMStrPtr2 = (ROM BYTE*)"\r\n.\r\n"; CRPeriod.Pos = NULL; if(RAMStrPtr) CRPeriod.Pos = (BYTE*)strstrrampgm((char*)RAMStrPtr, (ROM char*)"\r\n."); // No break here case SMTP_DATA_BODY: if(SMTPClient.Body.szRAM || SMTPClient.Body.szROM) { if(*ROMStrPtr2) { // Put the application data, doing the transparancy replacement of "\r\n." with "\r\n.." while(CRPeriod.Pos) { CRPeriod.Pos += 3; RAMStrPtr += TCPPutArray(MySocket, RAMStrPtr, CRPeriod.Pos-RAMStrPtr); if(RAMStrPtr == CRPeriod.Pos) { if(!TCPPut(MySocket, '.')) { CRPeriod.Pos -= 3; break; } } else { CRPeriod.Pos -= 3; break; } CRPeriod.Pos = (BYTE*)strstrrampgm((char*)RAMStrPtr, (ROM char*)"\r\n."); } // If we get down here, either all replacements have been made or there is no remaining space in the TCP output buffer RAMStrPtr = TCPPutString(MySocket, RAMStrPtr); ROMStrPtr2 = TCPPutROMString(MySocket, ROMStrPtr2); TCPFlush(MySocket); } } else { if(SMTPFlags.bits.ReadyToFinish) { if(*ROMStrPtr2) { ROMStrPtr2 = TCPPutROMString(MySocket, ROMStrPtr2); TCPFlush(MySocket); } } } if(*ROMStrPtr2 == 0u) { SMTPState++; } break; case SMTP_QUIT_INIT: SMTPState++; ROMStrPtr = (ROM BYTE*)"QUIT\r\n"; // No break here case SMTP_QUIT: if(*ROMStrPtr) { ROMStrPtr = TCPPutROMString(MySocket, ROMStrPtr); TCPFlush(MySocket); } if(*ROMStrPtr == 0u) { TransportState = TRANSPORT_CLOSE; } break; // Default case needed to supress compiler diagnostics default: break; } break; case TRANSPORT_CLOSE: // Close the socket so it can be used by other modules TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; // Go back to doing nothing TransportState = TRANSPORT_HOME; break; } }
/***************************************************************************** * * Cloud_GetCmd * * \param pbuf - string buffer containing data to be sent * bufsize - number of bytes to send * * \return 1 success; 0 failure * * \brief Writes data to Exosite cloud * *****************************************************************************/ int Cloud_GetCmd() { int length; char DataLen[10]; // int http_status = 0; char *cmp_ss = "Content-Length:"; char *cmp = cmp_ss; DWORD serverip = 0; const unsigned char server[6] = SERVERIP ; serverip = (server[3] << 24 & 0xff000000) | (server[2] << 16 & 0xff0000) | (server[1] << 8 & 0xff00) | (server[0] & 0xff); long w, r; char rev[300]; unsigned char len; char *p; unsigned char crlf = 0; int time_out = 0; int tx_buff_size = 250; int tmp_len =0 ; if(status_code == STATUS_INIT||status_code == STATUS_END){ if (sock == INVALID_SOCKET) { sock = TCPOpen(serverip, TCP_OPEN_IP_ADDRESS, HTTP_PORT, TCP_PURPOSE_TCP_CLIENT); // TCP_OPEN_RAM_HOST for using dns name as server name // TCPOpen(serverip, TCP_OPEN_IP_ADDRESS, server_port, TCP_PURPOSE_GENERIC_TCP_CLIENT); if (sock == INVALID_SOCKET) { status_code = STATUS_INIT; // LEDS_OFF(); // LEDS_ON(); return 0; } status_code = STATUS_READY; } else status_code == STATUS_READY; } else if(status_code == STATUS_READY) { if(sent_header) DelayMs(20); w = TCPIsPutReady(sock); if(w<=250ul) { return 0; } if(sent_header){ memset(header, 0, sizeof(header)); length = PostHeaderGenerate("/sendcmd.php", command, 0, 0); remain_count =0 ; sent_header = FALSE; sent_count = 0; } // LED2_ON(); LED1_OFF(); int send_len = strlen(&header[remain_count]); // LED2_ON(); LED1_OFF(); //if(send_len > 254) {LED2_ON(); LED1_OFF()}; /* The max size of sliding window for TCP packet is 254? after testing. * Don't know the reason, but if we set the number of sending data to 250, * the program works fine. * */ tmp_len = send_len>250? 250:send_len; // int tmp_len = IHMS_SocketSend(sock, &header[sent_count], send_len ); tmp_len = TCPPutArray(sock, (BYTE *) &header[remain_count], tmp_len); TCPFlush((TCP_SOCKET)sock); LED2_ON(); LED1_OFF(); if(tmp_len<send_len) { remain_count += tmp_len; return 0; } memset(header, 0, sizeof(header)); sent_count = 0; remain_count = 0; status_code = STATUS_RCV; } else if(status_code == STATUS_RCV) { DelayMs(20); r = TCPIsGetReady((TCP_SOCKET) sock); if(r<200u){ LED2_ON(); return 0;} // now read all data in RX buffer int count = 0; do { r = TCPGetArray((TCP_SOCKET)sock, (BYTE *)&rev[count], 300); count = count + r; rev[count]=0; r = TCPIsGetReady((TCP_SOCKET) sock); }while(r>0u); rev[count] = 0 ; TCPClose((TCP_SOCKET)sock); status_code = STATUS_END; sock = INVALID_SOCKET; status_code = STATUS_END; sent_header = TRUE; //now it's time to read time command = GetServerCmd(rev, "cmd="); cmd_no = GetServerCmd(rev, "no="); return 1; } return 0; }
void ReceiveEthernetCmds() { WORD wMaxGet, wBytesRead; BYTE b; static enum _TCPServerState { SM_HOME = 0, SM_LISTENING, SM_CLOSING, } TCPServerState = SM_HOME; switch(TCPServerState) { case SM_HOME: // Allocate a socket for this server to listen and accept connections on MySocket = TCPOpen(0, TCP_OPEN_SERVER, SERVER_PORT, TCP_PURPOSE_GENERIC_TCP_SERVER); if(MySocket == INVALID_SOCKET) return; TCPServerState = SM_LISTENING; break; case SM_LISTENING: // See if anyone is connected to us if(!TCPIsConnected(MySocket)) return; // Figure out how many bytes have been received and how many we can transmit. wMaxGet = TCPIsGetReady(MySocket); // Get TCP RX FIFO byte count // Read the data into the buffer wBytesRead = 0; while (wBytesRead < wMaxGet) { if(!TCPGet(MySocket, &b)) break; // Byte NOT read... (No connection or no data to read) if(b == 10 || b == 13) { // Ignore newline characters } else { EthernetBuffer[EB_Write] = b; if( (EB_Write+1) % ETHERNET_BUFFER_SIZE != EB_Read) // check if buffer full EB_Write++; EB_Write %= ETHERNET_BUFFER_SIZE; } wBytesRead++; } break; case SM_CLOSING: // Close the socket connection. TCPClose(MySocket); TCPServerState = SM_HOME; break; } ProcessBufferData(); }
void NIST_DAYTIME_Client(void) { WORD w; char NistRspBuffer[31]; BCD_RTCC rtc_time; static DWORD NistIP_addr =0; static DWORD Timer; static TCP_SOCKET sock = INVALID_SOCKET; switch (ThisState) { case SM_START: if (NistIP_addr == 0) // initialize the IP address for the time server to call NistIP_addr = WX.TimeServer.NIST1.Val; else if (NistIP_addr == WX.TimeServer.NIST1.Val) // toggle server address every time we try to call NistIP_addr = WX.TimeServer.NIST2.Val; else NistIP_addr = WX.TimeServer.NIST1.Val; // Connect a socket to the remote TCP server //sock = TCPOpen((DWORD) NIST_TIME_URL, TCP_OPEN_ROM_HOST, NIST_DAYTIME_PORT, TCP_PURPOSE_DEFAULT); // or with IP address ( faster, and uses less space in eeprom) // sock = TCPOpen((DWORD) "128.138.140.44", TCP_OPEN_ROM_HOST, NIST_DAYTIME_PORT, TCP_PURPOSE_DEFAULT); sock = TCPOpen( NistIP_addr, TCP_OPEN_IP_ADDRESS, NIST_DAYTIME_PORT, TCP_PURPOSE_DEFAULT); // Abort operation if no socket of proper type is available // If this ever happens, you need to go add one to TCPIPConfig.h if (sock == INVALID_SOCKET) { putrsUART((ROM char*) "NIST ERROR: no Socket of proper type defined in .h file\r\n"); ThisState = SM_IDLE; break; } ThisState++; Timer = TickGet(); putrsUART((ROM char*) "NIST waiting for socket connect on "); DisplayIPValue((IP_ADDR) NistIP_addr); putsUART(" Port 13\r\n"); break; case SM_SOCKET_OBTAINED: // Wait for the remote server to accept our connection request if (!TCPIsConnected(sock)) { // Time out if too much time is spent in this state if (TickGet() - Timer > NIST_TIMEOUT * TICK_SECOND) { putrsUART((ROM char*) "NIST connection timed out,aborting\r\n"); // Close the socket so it can be used by other modules ThisState = SM_DISCONNECT; } break; } Timer = TickGet(); ThisState++; break; case SM_PROCESS_RESPONSE: // collect the time data output from the sever and/or react to a Disconnect from the server // The Server automatically disconnects from the client after it outputs the data w = sizeof (NistRspBuffer) - 1; if (TCPIsGetReady(sock) >= w) { NistRspBuffer[28] = 0xff; w = TCPGetArray(sock, (unsigned char *)NistRspBuffer, w); if (NistRspBuffer[28] - '0' < 2) // The time servers health status { putrsUART((ROM char*) "NIST got good time\r\n"); //extracting the time from the response and setting the RTC clock rtc_time.yr = ((NistRspBuffer[7] - '0') << 4) + (NistRspBuffer[8] - '0'); rtc_time.mth = ((NistRspBuffer[10] - '0') << 4) + (NistRspBuffer[11] - '0'); rtc_time.day = ((NistRspBuffer[13] - '0') << 4) + (NistRspBuffer[14] - '0'); rtc_time.hr = ((NistRspBuffer[16] - '0') << 4) + (NistRspBuffer[17] - '0'); rtc_time.min = ((NistRspBuffer[19] - '0') << 4) + (NistRspBuffer[20] - '0'); rtc_time.sec = ((NistRspBuffer[22] - '0') << 4) + (NistRspBuffer[23] - '0'); // TT field ==0 indicates Standard time in efect, NOTE sotred in decimal format rtc_time.TT = ((NistRspBuffer[25] - '0') *10) + (NistRspBuffer[26] - '0'); RTC_Set_BCD_time(&rtc_time); // SET THE RTC with the current time NistGotGoodTime = TRUE; // set flag that we got good time } else putrsUART((ROM char*) "NIST server has healt issues\r\n"); ThisState = SM_DISCONNECT; } else { // wait to get data and abort if it takes too long if (TickGet() - Timer > NIST_TIMEOUT * TICK_SECOND) { putrsUART((ROM char*) "Nist data timeout, aborting\r\n"); ThisState = SM_DISCONNECT; break; } } if (!TCPIsConnected(sock)) { // If the Server disconnects before we do putrsUART((ROM char*) "NIST Server disconnected\r\n"); ThisState = SM_DISCONNECT; } break; case SM_DISCONNECT: // Close the socket so it can be used by other modules putrsUART((ROM char*) "NIST Client disconnected\r\n"); TCPDisconnect(sock); // This sends a "RST" TCPDisconnect(sock); // This sends a "FIN" sock = INVALID_SOCKET; if (NistGotGoodTime ) { ThisState = SM_IDLE; } else ThisState = SM_RETRY; break; case SM_RETRY: Timer = TickGet(); ThisState++; break; case SM_RETRY_DELAY: if (TickGet() - Timer > NIST_TIMEOUT * TICK_SECOND) ThisState = SM_START; break; case SM_IDLE: default: break; } }
void ModbusCmdTask(void) { static enum _BridgeState { SM_HOME = 0, SM_SOCKET_OBTAINED } BridgeState = SM_HOME; static TCP_SOCKET MySocket = INVALID_SOCKET; switch(BridgeState) { case SM_HOME: putrsUART((ROM char*)"\r\n in modbus sm home."); #if defined(DEBUG_TCP_CLIENT) //客户端 // Connect a socket to the remote TCP server MySocket = TCPOpen((DWORD)"192.168.1.36", TCP_OPEN_ROM_HOST, 502, TCP_PURPOSE_MODBUS_SERVER0); #else //服务器 MySocket = TCPOpen(0, TCP_OPEN_SERVER, 502, TCP_PURPOSE_MODBUS_SERVER0); #endif // Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available // If this ever happens, you need to go add one to TCPIPConfig.h if(MySocket == INVALID_SOCKET) break; // Eat the first TCPWasReset() response so we don't // infinitely create and reset/destroy client mode sockets TCPWasReset(MySocket); // We have a socket now, advance to the next state BridgeState = SM_SOCKET_OBTAINED; break; case SM_SOCKET_OBTAINED: if(TCPWasReset(MySocket)) { // Optionally discard anything in the UART FIFOs //RXHeadPtr = vUARTRXFIFO; //RXTailPtr = vUARTRXFIFO; //TXHeadPtr = vUARTTXFIFO; //TXTailPtr = vUARTTXFIFO; // If we were a client socket, close the socket and attempt to reconnect #if defined(DEBUG_TCP_CLIENT) TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; BridgeState = SM_HOME; break; #endif } // Don't do anything if nobody is connected to us if(!TCPIsConnected(MySocket)) { break; } ModbusTcpRxHandle(MySocket); break; default: BridgeState = SM_HOME; break; } }
/********************************************************************* * Function: void CAN2TCPBridgeTask(void) * * PreCondition: Stack is initialized() * * Input: None * * Output: None * * Side Effects: None * * Overview: None * * Note: None ********************************************************************/ void CAN2TCPBridgeTask(void) { static enum _BridgeState { SM_HOME = 0, SM_SOCKET_OBTAINED } BridgeState = SM_HOME; static TCP_SOCKET MySocket = INVALID_SOCKET; WORD wMaxPut, wMaxGet, w; BYTE *RXHeadPtrShadow, *RXTailPtrShadow; BYTE *TXHeadPtrShadow, *TXTailPtrShadow; switch(BridgeState) { case SM_HOME: #if defined(USE_REMOTE_TCP_SERVER) // Connect a socket to the remote TCP server MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE); #else MySocket = TCPOpen(0, TCP_OPEN_SERVER, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE); #endif // Abort operation if no TCP socket of type TCP_PURPOSE_CAN_2_TCP_BRIDGE is available // If this ever happens, you need to go add one to TCPIPConfig.h if(MySocket == INVALID_SOCKET) break; // Eat the first TCPWasReset() response so we don't // infinitely create and reset/destroy client mode sockets TCPWasReset(MySocket); // We have a socket now, advance to the next state BridgeState = SM_SOCKET_OBTAINED; break; case SM_SOCKET_OBTAINED: // Reset all buffers if the connection was lost if(TCPWasReset(MySocket)) { // Optionally discard anything in the CAN FIFOs RXHeadPtr = vCANRXFIFO; RXTailPtr = vCANRXFIFO; TXHeadPtr = vCANTXFIFO; TXTailPtr = vCANTXFIFO; // If we were a client socket, close the socket and attempt to reconnect #if defined(USE_REMOTE_TCP_SERVER) TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; BridgeState = SM_HOME; break; #endif } // Don't do anything if nobody is connected to us if(!TCPIsConnected(MySocket)) break; // Read FIFO pointers into a local shadow copy. Some pointers are volatile // (modified in the ISR), so we must do this safely by disabling interrupts RXTailPtrShadow = (BYTE*)RXTailPtr; TXHeadPtrShadow = (BYTE*)TXHeadPtr; CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE); CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE); RXHeadPtrShadow = (BYTE*)RXHeadPtr; TXTailPtrShadow = (BYTE*)TXTailPtr; CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); if(TXHeadPtrShadow != TXTailPtrShadow) CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE); // // Transmit pending data that has been placed into the CAN RX FIFO (in the ISR) // wMaxPut = TCPIsPutReady(MySocket); // Get TCP TX FIFO space wMaxGet = RXHeadPtrShadow - RXTailPtrShadow; // Get CAN RX FIFO byte count if(RXHeadPtrShadow < RXTailPtrShadow) wMaxGet += sizeof(vCANRXFIFO); if(wMaxPut > wMaxGet) // Calculate the lesser of the two wMaxPut = wMaxGet; if(wMaxPut) // See if we can transfer anything { // Transfer the data over. Note that a two part put // may be needed if the data spans the vCANRXFIFO // end to start address. w = vCANRXFIFO + sizeof(vCANRXFIFO) - RXTailPtrShadow; if(wMaxPut >= w) { TCPPutArray(MySocket, RXTailPtrShadow, w); RXTailPtrShadow = vCANRXFIFO; wMaxPut -= w; } TCPPutArray(MySocket, RXTailPtrShadow, wMaxPut); RXTailPtrShadow += wMaxPut; // No flush. The stack will automatically flush and do // transmit coallescing to minimize the number of TCP // packets that get sent. If you explicitly call TCPFlush() // here, latency will go down, but so will max throughput // and bandwidth efficiency. } // // Transfer received TCP data into the CAN TX FIFO for future transmission (in the ISR) // wMaxGet = TCPIsGetReady(MySocket); // Get TCP RX FIFO byte count wMaxPut = TXTailPtrShadow - TXHeadPtrShadow - 1;// Get CAN TX FIFO free space if(TXHeadPtrShadow >= TXTailPtrShadow) wMaxPut += sizeof(vCANTXFIFO); if(wMaxPut > wMaxGet) // Calculate the lesser of the two wMaxPut = wMaxGet; if(wMaxPut) // See if we can transfer anything { // Transfer the data over. Note that a two part put // may be needed if the data spans the vCANTXFIFO // end to start address. w = vCANTXFIFO + sizeof(vCANTXFIFO) - TXHeadPtrShadow; if(wMaxPut >= w) { TCPGetArray(MySocket, TXHeadPtrShadow, w); TXHeadPtrShadow = vCANTXFIFO; wMaxPut -= w; } TCPGetArray(MySocket, TXHeadPtrShadow, wMaxPut); TXHeadPtrShadow += wMaxPut; } // Write local shadowed FIFO pointers into the volatile FIFO pointers. CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE); CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE); RXTailPtr = (volatile BYTE*)RXTailPtrShadow; TXHeadPtr = (volatile BYTE*)TXHeadPtrShadow; CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); if(TXHeadPtrShadow != TXTailPtrShadow) CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE); break; } }
/***************************************************************************** Function: void GenericTCPServer(void) Summary: Implements a simple ToUpper TCP Server. Description: This function implements a simple TCP server. The function is invoked periodically by the stack to listen for incoming connections. When a connection is made, the server reads all incoming data, transforms it to uppercase, and echos it back. This example can be used as a model for many TCP server applications. Precondition: TCP is initialized. Parameters: None Returns: None ***************************************************************************/ void GenericTCPServer(void) { BYTE i,j; WORD w, w2; BYTE AppBuffer[32]; WORD wMaxGet, wMaxPut, wCurrentChunk; static TCP_SOCKET MySocket; static enum _TCPServerState { SM_HOME = 0, SM_LISTENING, SM_CLOSING, } TCPServerState = SM_HOME; switch(TCPServerState) { case SM_HOME: // Allocate a socket for this server to listen and accept connections on MySocket = TCPOpen(0, TCP_OPEN_SERVER, SERVER_PORT, TCP_PURPOSE_GENERIC_TCP_SERVER); if(MySocket == INVALID_SOCKET) return; tcptxbuffer[0]=0;tcptxbufferpoint=0; TCPServerState = SM_LISTENING; break; case SM_LISTENING: // See if anyone is connected to us if(!TCPIsConnected(MySocket)) { setspeed(0,0); LED0_IO=1; LED1_IO=0; return; } // Figure out how many bytes have been received and how many we can transmit. wMaxGet = TCPIsGetReady(MySocket); // Get TCP RX FIFO byte count wMaxPut = TCPIsPutReady(MySocket); // Get TCP TX FIFO free space // Make sure we don't take more bytes out of the RX FIFO than we can put into the TX FIFO // if(wMaxPut < wMaxGet) // wMaxGet = wMaxPut; // Process all bytes that we can // This is implemented as a loop, processing up to sizeof(AppBuffer) bytes at a time. // This limits memory usage while maximizing performance. Single byte Gets and Puts are a lot slower than multibyte GetArrays and PutArrays. wCurrentChunk = sizeof(AppBuffer); if (!wMaxGet) { w=tcptxbufferpoint; if (w>wMaxPut) { w=wMaxPut; } if (w) { TCPPutArray(MySocket, (BYTE*)&tcptxbuffer[0], w); if (tcptxbufferpoint!=w) { tcptxbufferpoint-=w; memcpy((BYTE*)&tcptxbuffer[0],(BYTE*)&tcptxbuffer[w],tcptxbufferpoint); } else tcptxbufferpoint=0; } } for(w = 0; w < wMaxGet; w += sizeof(AppBuffer)) { // Make sure the last chunk, which will likely be smaller than sizeof(AppBuffer), is treated correctly. if(w + sizeof(AppBuffer) > wMaxGet) wCurrentChunk = wMaxGet - w; // Transfer the data out of the TCP RX FIFO and into our local processing buffer. TCPGetArray(MySocket, AppBuffer, wCurrentChunk); j=0; for(w2 = 0; w2 < wCurrentChunk; w2++) { i = AppBuffer[w2]; putcomsdata(i); } // Transfer the data out of our local processing buffer and into the TCP TX FIFO. // TCPPutArray(MySocket, AppBuffer, wCurrentChunk); } TCPFlush(MySocket); // No need to perform any flush. TCP data in TX FIFO will automatically transmit itself after it accumulates for a while. If you want to decrease latency (at the expense of wasting network bandwidth on TCP overhead), perform and explicit flush via the TCPFlush() API. break; case SM_CLOSING: // Close the socket connection. TCPClose(MySocket); TCPServerState = SM_HOME; break; } }
/***************************************************************************** Function: int connect( SOCKET s, struct sockaddr* name, int namelen ) Summary: This function connects to the peer communications end point. Description: The connect function assigns the address of the peer communications endpoint. For stream sockets, connection is established between the endpoints. For datagram sockets, an address filter is established between the endpoints until changed with another connect() function. Precondition: socket function should be called. Parameters: s - Socket descriptor returned from a previous call to socket. name - pointer to the sockaddr structure containing the peer address and port number. namelen - length of the sockaddr structure. Returns: If the connect() function succeeds, it returns 0. Otherwise, the value SOCKET_ERROR is returned to indicate an error condition. For stream based socket, if the connection is not established yet, connect returns SOCKET_CNXN_IN_PROGRESS. Remarks: None. ***************************************************************************/ int connect( SOCKET s, struct sockaddr* name, int namelen ) { struct BSDSocket *pSock; struct sockaddr_in *addr; DWORD remoteIP; WORD remotePort; if( s >= BSD_SOCKET_COUNT ) return SOCKET_ERROR; pSock = &BSDSocketArray[s]; if( pSock->bsdState < SKT_CREATED ) return SOCKET_ERROR; if( (unsigned int)namelen < sizeof(struct sockaddr_in)) return SOCKET_ERROR; addr = (struct sockaddr_in *)name; remotePort = addr->sin_port; remoteIP = addr->sin_addr.S_un.S_addr; if( remoteIP == 0 || remotePort == 0 ) return SOCKET_ERROR; if( pSock->SocketType == SOCK_STREAM ) { switch(pSock->bsdState) { case SKT_EST: return 0; // already established case SKT_IN_PROGRESS: if(!TCPIsConnected(pSock->SocketID)) { pSock->bsdState = SKT_IN_PROGRESS; return SOCKET_CNXN_IN_PROGRESS; } if(pSock->SocketID != INVALID_SOCKET) { pSock->bsdState = SKT_EST; return 0; //success } break; case SKT_CREATED: case SKT_BOUND: pSock->SocketID = TCPOpen(remoteIP, TCP_OPEN_IP_ADDRESS, remotePort, TCP_PURPOSE_BERKELEY_CLIENT); if(pSock->SocketID == INVALID_SOCKET) return SOCKET_ERROR; if(!TCPIsConnected(pSock->SocketID)) { pSock->bsdState = SKT_IN_PROGRESS; return SOCKET_CNXN_IN_PROGRESS; } if(pSock->SocketID != INVALID_SOCKET) { pSock->bsdState = SKT_EST; return 0; //success } default: return SOCKET_ERROR; } } else { // UDP: remote port is used as a filter only. Need to call connect when using send/recv // calls. no need to call 'connect' if using sendto/recvfrom calls. pSock->remotePort = remotePort; pSock->remoteIP = remoteIP; pSock->bsdState = SKT_READY; return 0; //success } return SOCKET_ERROR; }
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 = TCPOpen((PTR_BASE)&TCPGetRemoteInfo(FTPSocket)->remote, TCP_OPEN_NODE_INFO, FTPDataPort.Val, TCP_PURPOSE_FTP_DATA); // Make sure that a valid socket was available and returned // If not, return with an error if(FTPDataSocket == INVALID_SOCKET) { FTPResponse = FTP_RESP_DATA_NO_SOCKET; return TRUE; } smFTPCommand = SM_FTP_CMD_WAIT; } break; case SM_FTP_CMD_WAIT: if ( TCPIsConnected(FTPDataSocket) ) { #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) ) { #if defined(FTP_PUT_ENABLED) MPFSPut(v); #endif } FTPFileHandle = MPFSPutEnd(); } else if ( !TCPIsConnected(FTPDataSocket) ) { #if defined(FTP_PUT_ENABLED) MPFSClose(); #endif TCPDisconnect(FTPDataSocket); FTPDataSocket = INVALID_SOCKET; FTPResponse = FTP_RESP_DATA_CLOSE; return TRUE; } } return FALSE; }
/********************************************************************* * Function: void GenericTCPServer(void) * * PreCondition: Stack is initialized() * * Input: None * * Output: None * * Side Effects: None * * Overview: None * * Note: None ********************************************************************/ void GenericTCPServer(void) { BYTE i; WORD w, w2; BYTE AppBuffer[32]; WORD wMaxGet, wMaxPut, wCurrentChunk; static TCP_SOCKET MySocket; static enum _TCPServerState { SM_HOME = 0, SM_LISTENING, } TCPServerState = SM_HOME; switch(TCPServerState) { case SM_HOME: // Allocate a socket for this server to listen and accept connections on MySocket = TCPOpen(0, TCP_OPEN_SERVER, SERVER_PORT, TCP_PURPOSE_GENERIC_TCP_SERVER); if(MySocket == INVALID_SOCKET) { #ifdef USE_LCD strcpypgm2ram((char*)LCDText, "Error: Increase MAX_TCP_SOCKETS"); LCDUpdate(); #endif return; } TCPServerState = SM_LISTENING; break; case SM_LISTENING: // See if anyone is connected to us if(!TCPIsConnected(MySocket)) return; // Figure out how many bytes have been received and how many we can transmit. wMaxGet = TCPIsGetReady(MySocket); // Get TCP RX FIFO byte count wMaxPut = TCPIsPutReady(MySocket); // Get TCP TX FIFO free space // Make sure we don't take more bytes out of the RX FIFO than we can put into the TX FIFO if(wMaxPut < wMaxGet) wMaxGet = wMaxPut; // Process all bytes that we can // This is implemented as a loop, processing up to sizeof(AppBuffer) bytes at a time. // This limits memory usage while maximizing performance. Single byte Gets and Puts are a lot slower than multibyte GetArrays and PutArrays. wCurrentChunk = sizeof(AppBuffer); for(w = 0; w < wMaxGet; w += sizeof(AppBuffer)) { // Make sure the last chunk, which will likely be smaller than sizeof(AppBuffer), is treated correctly. if(w + sizeof(AppBuffer) > wMaxGet) wCurrentChunk = wMaxGet - w; // Transfer the data out of the TCP RX FIFO and into our local processing buffer. TCPGetArray(MySocket, AppBuffer, wCurrentChunk); // Perform the "ToUpper" operation on each data byte for(w2 = 0; w2 < wCurrentChunk; w2++) { i = AppBuffer[w2]; if(i >= 'a' && i <= 'z') { i -= ('a' - 'A'); AppBuffer[w2] = i; } } // Transfer the data out of our local processing buffer and into the TCP TX FIFO. TCPPutArray(MySocket, AppBuffer, wCurrentChunk); } // No need to perform any flush. TCP data in TX FIFO will automatically transmit itself after it accumulates for a while. If you want to decrease latency (at the expense of wasting network bandwidth on TCP overhead), perform and explicit flush via the TCPFlush() API. break; } }
void TCPTXPerformanceTask(void) { static TCP_SOCKET MySocket = INVALID_SOCKET; static DWORD dwTimeStart; static DWORD dwBytesSent; static DWORD_VAL dwVLine; BYTE vBuffer[10]; static BYTE vBytesPerSecond[12]; WORD w; DWORD dw; QWORD qw; // Start the TCP server, listening on PERFORMANCE_PORT if(MySocket == INVALID_SOCKET) { MySocket = TCPOpen(0, TCP_OPEN_SERVER, TX_PERFORMANCE_PORT, TCP_PURPOSE_TCP_PERFORMANCE_TX); // Abort operation if no TCP socket of type TCP_PURPOSE_TCP_PERFORMANCE_TEST is available // If this ever happens, you need to go add one to TCPIPConfig.h if(MySocket == INVALID_SOCKET) return; dwVLine.Val = 0; dwTimeStart = TickGet(); vBytesPerSecond[0] = 0; // Initialize empty string right now dwBytesSent = 0; } // See how many bytes we can write to the TX FIFO // If we can't fit a single line of data in, then // lets just wait for now. w = TCPIsPutReady(MySocket); if(w < 12+27+5+32u) return; vBuffer[0] = '0'; vBuffer[1] = 'x'; // Transmit as much data as the TX FIFO will allow while(w >= 12+27+5+32u) { // Convert line counter to ASCII hex string vBuffer[2] = btohexa_high(dwVLine.v[3]); vBuffer[3] = btohexa_low(dwVLine.v[3]); vBuffer[4] = btohexa_high(dwVLine.v[2]); vBuffer[5] = btohexa_low(dwVLine.v[2]); vBuffer[6] = btohexa_high(dwVLine.v[1]); vBuffer[7] = btohexa_low(dwVLine.v[1]); vBuffer[8] = btohexa_high(dwVLine.v[0]); vBuffer[9] = btohexa_low(dwVLine.v[0]); dwVLine.Val++; // Place all data in the TCP TX FIFO TCPPutArray(MySocket, vBuffer, sizeof(vBuffer)); dw = TickGet() - dwTimeStart; // Calculate exact bytes/second, less truncation if((dwVLine.v[0] & 0x3F) == 0x00) { qw = (QWORD)dwBytesSent * (TICK_SECOND/100); qw /= dw; ultoa((DWORD)qw, vBytesPerSecond); } TCPPutROMString(MySocket, (ROM BYTE*)": We are currently achieving "); TCPPutROMArray(MySocket, (ROM BYTE*)" ", 5-strlen((char*)vBytesPerSecond)); TCPPutString(MySocket, vBytesPerSecond); TCPPutROMString(MySocket, (ROM BYTE*)"00 bytes/second TX throughput.\r\n"); if(dw > TICK_SECOND) { dwBytesSent >>= 1; dwTimeStart += dw>>1; } w -= 12+27+5+32; dwBytesSent += 12+27+5+32; }
/********************************************************************* * 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; } }
/***************************************************************************** * * Cloud_Activate * * \param None * * \return 1 - activation success * 0 - activation failure * * \brief Called after Init has been run in the past, but maybe comms were * down and we have to keep trying * *****************************************************************************/ int Cloud_Activate(void) { int length; char DataLen[5]; int newcik = 0; // int http_status = 0; char *cmp_ss = "Content-Length:"; char *cmp = cmp_ss; DWORD serverip = 0; const unsigned char server[6] = SERVERIP; serverip = (server[3] << 24 & 0xff000000) | (server[2] << 16 & 0xff0000) | (server[1] << 8 & 0xff00) | (server[0] & 0xff); long w, r; char rev[300]; unsigned char strLen, len; unsigned char cik_len_valid = 0; char *p; unsigned char crlf = 0; unsigned char ciklen = 0; int time_out = 0; // Flag cloud_initialized is set by Cloud_Init() /* if (!cloud_initialized) { status_code = STATUS_INIT; return newcik; } */ // clean the content of http header array if(status_code == STATUS_INIT||status_code == STATUS_END){ //to launch a new HTTP POST operation, clean the content of header at first if (sock == INVALID_SOCKET) { sock = TCPOpen(serverip, TCP_OPEN_IP_ADDRESS, HTTP_PORT, TCP_PURPOSE_TCP_CLIENT); // TCP_OPEN_RAM_HOST for using dns name as server name // TCPOpen(serverip, TCP_OPEN_IP_ADDRESS, server_port, TCP_PURPOSE_GENERIC_TCP_CLIENT); if (sock == INVALID_SOCKET) { status_code = STATUS_INIT; // LEDS_OFF(); // LEDS_ON(); return 0; } status_code = STATUS_READY; } status_code == STATUS_READY; } else if(status_code == STATUS_READY) { // Get activation Serial Number DelayMs(20); w = TCPIsPutReady(sock); if(w<2000ul) { // StackTask(); // TCPFlush((TCP_SOCKET)sock); return 0; } // LED1_ON(); LED2_OFF(); // if(w>2000ul) { LED2_ON(); LED1_OFF();} // DelayMs(100); length = strlen(provision_info); IHMS_itoa(DataLen, length, 10); //make a string for length sendLine(sock, POSTDATA_LINE, "/activate.php"); sendLine(sock, HOST_LINE, NULL); sendLine(sock, CONTENT_LINE, NULL); // IHMS_SocketSend(sock, "Connection: close\r\n", sizeof("Connection: close\r\n")-1); sendLine(sock, LENGTH_LINE, DataLen); IHMS_SocketSend(sock, provision_info, length); status_code = STATUS_RCV; } else if(status_code == STATUS_RCV) { DelayMs(20); r = TCPIsGetReady((TCP_SOCKET) sock); if(r<234u){ LED2_ON(); return 0;} // now read all data in RX buffer int count = 0; do { r = TCPGetArray((TCP_SOCKET)sock, (BYTE *)&rev[count], 300); count = count + r; rev[count]=0; r = TCPIsGetReady((TCP_SOCKET) sock); }while(r>0u); rev[count] = 0 ; strLen = strlen(rev); len = strLen; p = rev; // Find 4 consecutive \r or \n - should be: \r\n\r\n while (0 < len && 4 > crlf) { if ('\r' == *p || '\n' == *p) { ++crlf; } else { crlf = 0; if (*cmp == *p) { // check the cik length from http response cmp++; if (cmp > cmp_ss + strlen(cmp_ss) - 1) cik_len_valid = 1; } else cmp = cmp_ss; } ++p; --len; } if(len>0) { LED1_ON(); LED2_OFF(); } // The body is the cik // TODO, be more robust - match Content-Length header value to CIK_LENGTH strncpy(CIK, p, CIK_LENGTH); CIK[40] = 0; newcik = 1; //IHMS_SocketClose(sock); TCPClose((TCP_SOCKET)sock); status_code = STATUS_END; sock = INVALID_SOCKET; return newcik; } // status_code = STATUS_INIT; return newcik; }
//maquina de estado onde trabalha com socket cliente void ClientSocketTCP(void) { static DWORD Timer; static TCP_SOCKET MySocket = INVALID_SOCKET; static enum generic_client { INICIA=0, AGUARDA_BOTAO, CONECTA, AGUARDA_CONEXAO, ENVIA_DADOS, DESCONECTA, }maquina_estado_cliente = INICIA; //toda maquina de estado roda aki switch(maquina_estado_cliente) { //////////////////////////////////////////////////////////////////////// case INICIA: Timer = TickGet(); maquina_estado_cliente = AGUARDA_BOTAO; break; //////////////////////////////////////////////////////////////////////// case AGUARDA_BOTAO: //pisca o led para informar a pilha rodando //if(TickGet() - Timer >= TICK_SECOND*3) if(!BUTTON0_IO) { if(TickGet() - Timer >= TICK_SECOND) { Timer = TickGet(); maquina_estado_cliente = CONECTA; } } else { Timer = TickGet(); } break; //////////////////////////////////////////////////////////////////////// case CONECTA: MySocket = TCPOpen((DWORD)&ServerName[0], 1, ServerPort, 0); if(MySocket == INVALID_SOCKET) break; maquina_estado_cliente=AGUARDA_CONEXAO; Timer = TickGet(); break; //////////////////////////////////////////////////////////////////////// case AGUARDA_CONEXAO: if(!TCPIsConnected(MySocket)) { //agurda o tick... if(TickGet()-Timer > 5*TICK_SECOND) { //fecha a porta senao consegir conecta durante um tempo TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; maquina_estado_cliente=AGUARDA_BOTAO; } break; } Timer = TickGet(); maquina_estado_cliente=ENVIA_DADOS; break; //////////////////////////////////////////////////////////////////////// case ENVIA_DADOS: if(TCPIsConnected(MySocket)) { TCPPutROMString(MySocket,(ROM BYTE*)"E ai Server\r\n"); TCPFlush(MySocket); maquina_estado_cliente = DESCONECTA; } else{maquina_estado_cliente = DESCONECTA;} break; //////////////////////////////////////////////////////////////////////// case DESCONECTA: TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; maquina_estado_cliente = AGUARDA_BOTAO; break; } }
/***************************************************************************** Function: void GenericTCPClient(void) Summary: Implements a simple HTTP client (over TCP). Description: This function implements a simple HTTP client, which operates over TCP. The function is called periodically by the stack, and waits for BUTTON1 to be pressed. When the button is pressed, the application opens a TCP connection to an Internet search engine, performs a search for the word "Microchip" on "microchip.com", and prints the resulting HTML page to the UART. This example can be used as a model for many TCP and HTTP client applications. Precondition: TCP is initialized. Parameters: None Returns: None ***************************************************************************/ void GenericTCPClient(void) { BYTE i; WORD w; BYTE vBuffer[9]; static DWORD Timer; static TCP_SOCKET MySocket = INVALID_SOCKET; static enum _GenericTCPExampleState { SM_HOME = 0, SM_SOCKET_OBTAINED, SM_PROCESS_RESPONSE, SM_DISCONNECT, SM_DONE } GenericTCPExampleState = SM_DONE; switch(GenericTCPExampleState) { case SM_HOME: // Connect a socket to the remote TCP server MySocket = TCPOpen((DWORD)&ServerName[0], TCP_OPEN_RAM_HOST, ServerPort, TCP_PURPOSE_GENERIC_TCP_CLIENT); // Abort operation if no TCP socket of type TCP_PURPOSE_GENERIC_TCP_CLIENT is available // If this ever happens, you need to go add one to TCPIPConfig.h if(MySocket == INVALID_SOCKET) break; #if defined(STACK_USE_UART) putrsUART((ROM char*)"\r\n\r\nConnecting using Microchip TCP API...\r\n"); #endif GenericTCPExampleState++; Timer = TickGet(); break; case SM_SOCKET_OBTAINED: // Wait for the remote server to accept our connection request if(!TCPIsConnected(MySocket)) { // Time out if too much time is spent in this state if(TickGet()-Timer > 5*TICK_SECOND) { // Close the socket so it can be used by other modules TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; GenericTCPExampleState--; } break; } Timer = TickGet(); // Make certain the socket can be written to if(TCPIsPutReady(MySocket) < 125u) break; // Place the application protocol data into the transmit buffer. For this example, we are connected to an HTTP server, so we'll send an HTTP GET request. TCPPutROMString(MySocket, (ROM BYTE*)"GET "); TCPPutROMString(MySocket, RemoteURL); TCPPutROMString(MySocket, (ROM BYTE*)" HTTP/1.0\r\nHost: "); TCPPutString(MySocket, ServerName); TCPPutROMString(MySocket, (ROM BYTE*)"\r\nConnection: close\r\n\r\n"); // Send the packet TCPFlush(MySocket); GenericTCPExampleState++; break; case SM_PROCESS_RESPONSE: // Check to see if the remote node has disconnected from us or sent us any application data // If application data is available, write it to the UART if(!TCPIsConnected(MySocket)) { GenericTCPExampleState = SM_DISCONNECT; // Do not break; We might still have data in the TCP RX FIFO waiting for us } // Get count of RX bytes waiting w = TCPIsGetReady(MySocket); // Obtian and print the server reply i = sizeof(vBuffer)-1; vBuffer[i] = '\0'; while(w) { if(w < i) { i = w; vBuffer[i] = '\0'; } w -= TCPGetArray(MySocket, vBuffer, i); #if defined(STACK_USE_UART) putsUART((char*)vBuffer); #endif // putsUART is a blocking call which will slow down the rest of the stack // if we shovel the whole TCP RX FIFO into the serial port all at once. // Therefore, let's break out after only one chunk most of the time. The // only exception is when the remote node disconncets from us and we need to // use up all the data before changing states. if(GenericTCPExampleState == SM_PROCESS_RESPONSE) break; } break; case SM_DISCONNECT: // Close the socket so it can be used by other modules // For this application, we wish to stay connected, but this state will still get entered if the remote server decides to disconnect TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; GenericTCPExampleState = SM_DONE; break; case SM_DONE: // Do nothing unless the user pushes BUTTON1 and wants to restart the whole connection/download process if(BUTTON1_IO == 0u) GenericTCPExampleState = SM_HOME; break; } }
void HTTPInit(void) { HCB[0].socket = TCPOpen(0, TCP_OPEN_SERVER, AppConfig.MyPort, TCP_PURPOSE_HTTP_SERVER); HCB[0].smHTTP = SM_HTTP_IDLE; }
/********************************************************************* * void IO2TCPBridgeTask(void) * * PreCondition: Stack is initialized() * * Input: None * * Output: None * * Side Effects: None * * Overview: None * * Note: None ********************************************************************/ void IO2TCPBridgeTask(void) { static enum _BridgeState { SM_HOME = 0, SM_SOCKET_OBTAINED } BridgeState = SM_HOME; static TCP_SOCKET MySocket = INVALID_SOCKET; WORD wMaxPut, wMaxGet, w; BYTE *RXHeadPtrShadow, *RXTailPtrShadow; BYTE *TXHeadPtrShadow, *TXTailPtrShadow; switch(BridgeState) { case SM_HOME: #if defined(USE_REMOTE_TCP_SERVER) // Connect a socket to the remote TCP server MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE); #else MySocket = TCPOpen(0, TCP_OPEN_SERVER, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE); #endif // Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available // If this ever happens, you need to go add one to TCPIPConfig.h if(MySocket == INVALID_SOCKET) break; // Eat the first TCPWasReset() response so we don't // infinitely create and reset/destroy client mode sockets TCPWasReset(MySocket); // We have a socket now, advance to the next state BridgeState = SM_SOCKET_OBTAINED; break; case SM_SOCKET_OBTAINED: // Reset all buffers if the connection was lost if(TCPWasReset(MySocket)) { // Optionally discard anything in the UART FIFOs //RXHeadPtr = vUARTRXFIFO; //RXTailPtr = vUARTRXFIFO; //TXHeadPtr = vUARTTXFIFO; //TXTailPtr = vUARTTXFIFO; // If we were a client socket, close the socket and attempt to reconnect #if defined(USE_REMOTE_TCP_SERVER) TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; BridgeState = SM_HOME; break; #endif } // Don't do anything if nobody is connected to us if(!TCPIsConnected(MySocket)) break; if(TRUE == TxData) { //TCPPutArray(MySocket, keyinfo, 1); TCPPut(MySocket, keyinfo); TxData = FALSE; } // No flush. The stack will automatically flush and do // transmit coallescing to minimize the number of TCP // packets that get sent. If you explicitly call TCPFlush() // here, latency will go down, but so will max throughput // and bandwidth efficiency. break; } }
//**************************************************************************** // Only internal use: // TCPGenericOpen callback function //**************************************************************************** int cTCPGenericOpen() { xSocket = INVALID_SOCKET; xSocket = TCPOpen((DWORD)&xIPAddress[0], xByte3 , xTCPPort, xByte2); return 0; }
/********************************************************************* * Function: void UART2TCPBridgeTask(void) * * PreCondition: Stack is initialized() * * Input: None * * Output: None * * Side Effects: None * * Overview: None * * Note: None ********************************************************************/ void UART2TCPBridgeTask(void) { static enum _BridgeState { SM_HOME = 0, SM_SOCKET_OBTAINED } BridgeState = SM_HOME; static TCP_SOCKET MySocket = INVALID_SOCKET; WORD wMaxPut, wMaxGet, w; BYTE *RXHeadPtrShadow, *RXTailPtrShadow; BYTE *TXHeadPtrShadow, *TXTailPtrShadow; switch(BridgeState) { case SM_HOME: #if defined(USE_REMOTE_TCP_SERVER) // Connect a socket to the remote TCP server MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE); #else MySocket = TCPOpen(0, TCP_OPEN_SERVER, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE); #endif // Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available // If this ever happens, you need to go add one to TCPIPConfig.h if(MySocket == INVALID_SOCKET) break; // Eat the first TCPWasReset() response so we don't // infinitely create and reset/destroy client mode sockets TCPWasReset(MySocket); // We have a socket now, advance to the next state BridgeState = SM_SOCKET_OBTAINED; break; case SM_SOCKET_OBTAINED: // Reset all buffers if the connection was lost if(TCPWasReset(MySocket)) { // Optionally discard anything in the UART FIFOs //RXHeadPtr = vUARTRXFIFO; //RXTailPtr = vUARTRXFIFO; //TXHeadPtr = vUARTTXFIFO; //TXTailPtr = vUARTTXFIFO; // If we were a client socket, close the socket and attempt to reconnect #if defined(USE_REMOTE_TCP_SERVER) TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; BridgeState = SM_HOME; break; #endif } // Don't do anything if nobody is connected to us if(!TCPIsConnected(MySocket)) break; // Make sure to clear UART errors so they don't block all future operations #if defined(__18CXX) if(RCSTAbits.OERR) { RCSTAbits.CREN = 0; RCSTAbits.CREN = 1; LED1_IO ^= 1; } if(RCSTAbits.FERR) { BYTE dummy = RCREG; LED2_IO ^= 1; } #else if(U2STAbits.OERR) U2STAbits.OERR = 0; #endif // Read FIFO pointers into a local shadow copy. Some pointers are volatile // (modified in the ISR), so we must do this safely by disabling interrupts RXTailPtrShadow = (BYTE*)RXTailPtr; TXHeadPtrShadow = (BYTE*)TXHeadPtr; #if defined(__18CXX) PIE1bits.RCIE = 0; PIE1bits.TXIE = 0; #else IEC1bits.U2RXIE = 0; IEC1bits.U2TXIE = 0; #endif RXHeadPtrShadow = (BYTE*)RXHeadPtr; TXTailPtrShadow = (BYTE*)TXTailPtr; #if defined(__18CXX) PIE1bits.RCIE = 1; if(TXHeadPtrShadow != TXTailPtrShadow) PIE1bits.TXIE = 1; #else IEC1bits.U2RXIE = 1; if(TXHeadPtrShadow != TXTailPtrShadow) IEC1bits.U2TXIE = 1; #endif // // Transmit pending data that has been placed into the UART RX FIFO (in the ISR) // wMaxPut = TCPIsPutReady(MySocket); // Get TCP TX FIFO space wMaxGet = RXHeadPtrShadow - RXTailPtrShadow; // Get UART RX FIFO byte count if(RXHeadPtrShadow < RXTailPtrShadow) wMaxGet += sizeof(vUARTRXFIFO); if(wMaxPut > wMaxGet) // Calculate the lesser of the two wMaxPut = wMaxGet; if(wMaxPut) // See if we can transfer anything { // Transfer the data over. Note that a two part put // may be needed if the data spans the vUARTRXFIFO // end to start address. w = vUARTRXFIFO + sizeof(vUARTRXFIFO) - RXTailPtrShadow; if(wMaxPut >= w) { TCPPutArray(MySocket, RXTailPtrShadow, w); RXTailPtrShadow = vUARTRXFIFO; wMaxPut -= w; } TCPPutArray(MySocket, RXTailPtrShadow, wMaxPut); RXTailPtrShadow += wMaxPut; // No flush. The stack will automatically flush and do // transmit coallescing to minimize the number of TCP // packets that get sent. If you explicitly call TCPFlush() // here, latency will go down, but so will max throughput // and bandwidth efficiency. } // // Transfer received TCP data into the UART TX FIFO for future transmission (in the ISR) // wMaxGet = TCPIsGetReady(MySocket); // Get TCP RX FIFO byte count wMaxPut = TXTailPtrShadow - TXHeadPtrShadow - 1;// Get UART TX FIFO free space if(TXHeadPtrShadow >= TXTailPtrShadow) wMaxPut += sizeof(vUARTTXFIFO); if(wMaxPut > wMaxGet) // Calculate the lesser of the two wMaxPut = wMaxGet; if(wMaxPut) // See if we can transfer anything { // Transfer the data over. Note that a two part put // may be needed if the data spans the vUARTTXFIFO // end to start address. w = vUARTTXFIFO + sizeof(vUARTTXFIFO) - TXHeadPtrShadow; if(wMaxPut >= w) { TCPGetArray(MySocket, TXHeadPtrShadow, w); TXHeadPtrShadow = vUARTTXFIFO; wMaxPut -= w; } TCPGetArray(MySocket, TXHeadPtrShadow, wMaxPut); TXHeadPtrShadow += wMaxPut; } // Write local shadowed FIFO pointers into the volatile FIFO pointers. #if defined(__18CXX) PIE1bits.RCIE = 0; PIE1bits.TXIE = 0; #else IEC1bits.U2RXIE = 0; IEC1bits.U2TXIE = 0; #endif RXTailPtr = (volatile BYTE*)RXTailPtrShadow; TXHeadPtr = (volatile BYTE*)TXHeadPtrShadow; #if defined(__18CXX) PIE1bits.RCIE = 1; if(TXHeadPtrShadow != TXTailPtrShadow) PIE1bits.TXIE = 1; #else IEC1bits.U2RXIE = 1; if(TXHeadPtrShadow != TXTailPtrShadow) IEC1bits.U2TXIE = 1; #endif break; } }
/********************************************************************* * 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; } }
void twatchTasks(void){ //this state machine services the #twatch static enum _twitterTCPstate{ TWITTER_INIT=0, HOLD_COLOR, TWITTER_IDLE, TWITTER_SEARCH_TCP_START, TWITTER_SEARCH_TCP_SOCKET_OBTAINED, TWITTER_SEARCH_TCP_PROCESS_RESPONSE, TWITTER_SEARCH_TCP_DISCONNECT, } twitterTCPstate = TWITTER_INIT; //massive twitter parsing state machine static enum _HTTPstatus{ UNKNOWN=0, OK, ERROR, } HTTPstatus = UNKNOWN; //get and track HTTP status and handle errors static unsigned char HTTPheaderBuf[20]; //used to store HTTP headers static unsigned char HTTPheaderBufCnt; //pointer static BYTE HTTPretry=0, gotID=0;//extra static vars for twitter parser unsigned char tcpReadBytes, cnt; unsigned int tcpTotalBytes; //for TCPsocket length, can be >256 #define TCPBUF_LENGTH 50 //best size unsigned char tcpBuf[TCPBUF_LENGTH]; static DWORD Timer; static TCP_SOCKET TCPSocket = INVALID_SOCKET; static struct _timekeeper{ DWORD ticks; unsigned char minutes; unsigned char seconds; unsigned char runsec; //running seconds counter } time; //a minutes counter for determining when to refresh the search results if(TickGet() - time.ticks >= TICK_SECOND){ time.ticks = TickGet(); time.seconds++; time.runsec++; if(time.seconds>59){ time.seconds=0; time.minutes++; if(time.minutes>59){ time.minutes=0; } } } switch(twitterTCPstate){ case TWITTER_INIT: //setup JSON parser structs on first run searchParser.searchTag=textTag;//tag to search for searchParser.searchTagLength=(sizeof(textTag)-1);//length of search tag searchParser.valueBuffer=tweetBuf; //assign buffer to this struct searchParser.valueBufferLength=TWEETCHARS;//buffer length searchParser.valueEndChar='"'; //text tag, value ends with " nameParser.searchTag=nameTag;//tag to name for nameParser.searchTagLength=(sizeof(nameTag)-1);//length of name tag nameParser.valueBuffer=nameBuf; //assign buffer to this struct nameParser.valueBufferLength=NAMECHARS;//buffer length nameParser.valueEndChar='"'; //text tag, value ends with " max_idParser.searchTag=max_idTag;//tag to search for max_idParser.searchTagLength=(sizeof(max_idTag)-1);//length of search tag max_idParser.valueBuffer=lastidTempBuf; //assign buffer to this struct max_idParser.valueBufferLength=MAX_IDCHARS;//buffer length max_idParser.valueEndChar=','; //text tag, value ends with " max_idParser.valueBuffer[20]='\0'; //ensure 0 termination //zero the last ID before first call lastidBuf[0]='\0'; lastidBuf[1]='\0'; //reset printer UARTTX(0x1b); UARTTX('@'); //Control parameter command UARTTX(0x1b); UARTTX(0x37); UARTTX(0x07);//max printing dots UARTTX(0xFF);//heating time UARTTX(0x05); //heating interval twitterTCPstate=TWITTER_SEARCH_TCP_START; //start TCP data grabber next cycle break; case HOLD_COLOR: if(time.runsec<HOLD_SECONDS){ break; } twitterTCPstate=TWITTER_IDLE; case TWITTER_IDLE: //if this variable set, then start the refresh process //have we played all the buffered text if(T.cnt>0 && UART_EMPTY()){//step through text when idle if(T.t[T.read]==0xFF){//0xFF, end of tweet. reset line counter T.lncnt=0; }else{ UARTTX(T.t[T.read]); T.lncnt++; //send a LF at the end of each X characters if(T.lncnt==PRINTER_WIDTH){ UARTTX(0x0a); T.lncnt=0; twitterTCPstate=HOLD_COLOR;//next time hold solid color } } T.read++; //is this the final text? T.cnt--; if(T.cnt==0){//done with text time.runsec=0;//clear running counter for pause #ifndef DEBUG UARTTX(0x0a); UARTTX(0x0a); twitterTCPstate=HOLD_COLOR;//next time hold solid color #endif } }else if(time.seconds>=REFRESH_INTERVAL){ //if it has been at least X minutes, get tweet search results time.seconds=0; HTTPretry=0; //reset the number of retries twitterTCPstate=TWITTER_SEARCH_TCP_START; //start TCP data grabber next cycle } break; case TWITTER_SEARCH_TCP_START: //begins search for tweets //setup the search parser struct resetJSONparser(&nameParser); resetJSONparser(&searchParser); resetJSONparser(&max_idParser); gotID=0; //reset the ID finder T.cnt=0; //reset the tweet letter counter T.read=0; //reset the read pointer HTTPstatus = UNKNOWN; //clear the HTTP status checker HTTPheaderBufCnt=0; //connect to twitter TCPSocket = TCPOpen((DWORD)&ServerName[0], TCP_OPEN_RAM_HOST, ServerPort, TCP_PURPOSE_GENERIC_TCP_CLIENT); if(TCPSocket == INVALID_SOCKET) break; //abort on error twitterTCPstate=TWITTER_SEARCH_TCP_SOCKET_OBTAINED; Timer = TickGet(); break; case TWITTER_SEARCH_TCP_SOCKET_OBTAINED: //wait for server, with timeout if(!TCPIsConnected(TCPSocket)){ if(TickGet()-Timer > 5*TICK_SECOND){ TCPDisconnect(TCPSocket); TCPSocket = INVALID_SOCKET; twitterTCPstate--; } break; } Timer = TickGet(); if(TCPIsPutReady(TCPSocket) < 125u) break; //socket ready for writes? TCPPutROMString(TCPSocket, (ROM BYTE*)"GET "); //setup the HTTP GET request TCPPutROMString(TCPSocket, SearchURL); //JSON search datafeed URL //add the last ID to the JSON search URL. (usually requires urlencoding, but we have numbers only) //#ifdef 0 if(lastidBuf[0]!='\0'){ //don't put 0 length IDs into TCP, kills socket TCPPutString(TCPSocket, lastidBuf); //put the string in the TCP buffer } //#endif //form the rest of the HTTP request TCPPutROMString(TCPSocket, (ROM BYTE*)" HTTP/1.0\r\nHost: "); TCPPutString(TCPSocket, ServerName); TCPPutROMString(TCPSocket, (ROM BYTE*)"\r\nConnection: close\r\n\r\n"); TCPFlush(TCPSocket); //send the HTTP request to the Twitter server twitterTCPstate=TWITTER_SEARCH_TCP_PROCESS_RESPONSE; break; case TWITTER_SEARCH_TCP_PROCESS_RESPONSE: if(!TCPIsConnected(TCPSocket)) twitterTCPstate = TWITTER_SEARCH_TCP_DISCONNECT; //check for connection // Do not break; We might still have data in the TCP RX FIFO waiting for us tcpTotalBytes = TCPIsGetReady(TCPSocket); //how many bytes waiting? tcpReadBytes = TCPBUF_LENGTH; while(tcpTotalBytes){ //process server reply if(tcpTotalBytes < tcpReadBytes){ tcpReadBytes = tcpTotalBytes; } tcpTotalBytes -= TCPGetArray(TCPSocket, tcpBuf, tcpReadBytes); for(cnt=0;cnt<tcpReadBytes;cnt++){ UART2TX(tcpBuf[cnt]); //---------------// switch(HTTPstatus){ case UNKNOWN: //check header for response code before extracting tags HTTPheaderBuf[HTTPheaderBufCnt]=tcpBuf[cnt];//add to the headerbuf array if(HTTPheaderBufCnt<19) HTTPheaderBufCnt++; //if it won't overrun the array, increment the counter if(tcpBuf[cnt]==0x0d){//current character is a line break, examine the header for the response code //is it HTTP? if(HTTPheaderBuf[0]=='H' && HTTPheaderBuf[1]=='T' && HTTPheaderBuf[2]=='T' && HTTPheaderBuf[3]=='P' ){ //loop past /1.x and space HTTPheaderBufCnt=4; while(HTTPheaderBuf[HTTPheaderBufCnt]!=' '){ HTTPheaderBufCnt++; if(HTTPheaderBufCnt>19) break; //buffer overrun } HTTPheaderBufCnt++; //is it 200? (should be a ASCII->int loop that gets the actual value for error handling.... if( ((HTTPheaderBufCnt+2) < 20) && HTTPheaderBuf[HTTPheaderBufCnt]=='2' && HTTPheaderBuf[HTTPheaderBufCnt+1]=='0' && HTTPheaderBuf[HTTPheaderBufCnt+2]=='0'){ HTTPstatus=OK; }else{ HTTPstatus=ERROR; } } } break; case OK: if(tagSearch(tcpBuf[cnt], &nameParser)){//process the tweet for color data processname(nameParser.valueBufferCounter); } if(tagSearch(tcpBuf[cnt], &searchParser)){//process the tweet for color data processtweet(searchParser.valueBufferCounter); } if(gotID==0){//get only the first (highest) tweet ID to append to the URL next time if(tagSearch(tcpBuf[cnt], &max_idParser)){ addValueByte('\0', &max_idParser); for(gotID=0; gotID<21; gotID++){ lastidBuf[gotID]=lastidTempBuf[gotID];//only overwrite if comlete } gotID=1; } } break; case ERROR://do nothing because we need to clear the buffer break; } //------------------// }//for loop if(twitterTCPstate == TWITTER_SEARCH_TCP_PROCESS_RESPONSE) break; }//while break; case TWITTER_SEARCH_TCP_DISCONNECT: TCPDisconnect(TCPSocket); //close the socket TCPSocket = INVALID_SOCKET; //did not get valid HTML, retry, got no tags, retry once if no tags if(HTTPstatus!=OK ){ HTTPretry++; if(HTTPretry>(HTTP_MAX_RETRY-1)){//retry, then wait till next time... twitterTCPstate = TWITTER_IDLE; time.seconds=0; break; } twitterTCPstate = TWITTER_SEARCH_TCP_START; break; } HTTPretry=0; //success, clear number or retries twitterTCPstate = TWITTER_IDLE; break; }//switch
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; } }