/* ***************************************************************************** ** FUNCTION NAME: HttpRequest ** ** FUNCTION INPUTS: ** @char *hostname: host name. e.g. freedb.freedb.org ** @int port: http request port. e.g. 80 ** @char *uriBuf: http request uri with http request header ** @int timeout: timeout (unit:seconds) e.g. 30 ** @PHTTP_RESPONSE pHttp: HTTP_RESPONSE struct for return ** ** FUNCTION DESCRIPTION ** This function will create socket by hostname and port, then it will send ** uriBuf to server and wait it until timeout. If get response success, parse ** it and return with HTTP_REPONSE struct. ** ** FUNCTION OUTPUTS: ** ZAPP_SUCCESS -> success ** ZAPP_TIMEOUT -> timeout ** ZAPP_NETWORK -> cannot link to server ** ZAPP_FAILED -> other reason ** ** HISTORY: ** 2008-7-3 Steven Leong Created ***************************************************************************** */ int HttpRequest(char *hostname, int port, char *uriBuf, int timeout, PHTTP_RESPONSE pHttp) { int nRet; int fd; /* timeout policy */ int lefttime, starttime, curtime; if(hostname == NULL || uriBuf == NULL || pHttp == NULL) return ZAPP_FAILED; lefttime = timeout; starttime = GetUptime(); /* Create socket */ nRet = CreateTCPSenderByHostname(hostname, port, &fd, lefttime); if(nRet != ZAPP_SUCCESS){ switch(nRet){ case ZAPP_NETWORK: return ZAPP_NETWORK; case ZAPP_TIMEOUT: return ZAPP_TIMEOUT; } return ZAPP_FAILED; } // Calculate lefttime if((curtime = GetUptime()) > 0){ lefttime -= curtime - starttime; starttime = curtime; } if(lefttime <= 0){ close(fd); return ZAPP_TIMEOUT; } /* Send request */ if(write(fd, uriBuf, strlen(uriBuf)) <= 0){ close(fd); return ZAPP_FAILED; } nRet = HttpRead(fd, lefttime, pHttp); if(nRet != ZAPP_SUCCESS){ close(fd); if(nRet == ZAPP_TIMEOUT) return ZAPP_TIMEOUT; return ZAPP_FAILED; } /* Free socket */ close(fd); return ZAPP_SUCCESS; }
/* ***************************************************************************** ** FUNCTION NAME: CreateTCPSenderByHostname ** ** FUNCTION INPUTS: ** @char *hostname: e.g. www.google.cn ** @int port: port e.g. 80 ** @int *fd: fd for output ** @int timeout: how many seconds to timeout ** ** FUNCTION DESCRIPTION ** This function will create TCP sender with hostname ** ** FUNCTION OUTPUTS: ** Returns ZAPP_SUCCESS on success, or ZAPP_FAILED on creating socket failed. ** or ZAPP_NETWORK on gethostbyname failed(Not network). or ZAPP_TIMEOUT on timeout. ** ** HISTORY: ** 2008-7-2 Steven Leong Created ***************************************************************************** */ int CreateTCPSenderByHostname(char *hostname, int port, int *fd, int timeout) { struct hostent *hptr; char **ptr; char strArray[32] = {0}; char *ptrIpAddr = NULL; int nAddrType, res; U32 lefttime, starttime, curtime; lefttime = timeout; starttime = GetUptime(); *fd = -1; dprintf("hostname->%s\n", hostname); if((hptr = gethostbyname(hostname)) == NULL){ return ZAPP_NETWORK; } if((curtime = GetUptime()) > 0){ lefttime -= curtime - starttime; starttime = curtime; } nAddrType = hptr->h_addrtype; if(nAddrType == AF_INET || nAddrType == AF_INET6){ ptr=hptr->h_addr_list; for(;*ptr!=NULL;ptr++){ ptrIpAddr=(char*)inet_ntop(nAddrType,*ptr,strArray,(sizeof(strArray))); dprintf("IPAddr->%s\n", ptrIpAddr); res = CreateSocket(TCPSOCKET, SENDER, ptrIpAddr, port, fd, lefttime); if(res == ZAPP_SUCCESS) break; if((curtime = GetUptime()) > 0){ lefttime -= curtime - starttime; starttime = curtime; if(lefttime <= 0){ /* timeout */ return ZAPP_TIMEOUT; } } } } if(*fd <= 0) return ZAPP_FAILED; return ZAPP_SUCCESS; }
int GetItemFromFourLight(ISmartFrame *pISMartFrame, Item *pitem) { /*mac*/ memcpy((void*)pitem->mac, &pISMartFrame->sourceMac[6], MAC_SIZE); /*类型*/ pitem->type = pISMartFrame->funCode.dev; /*状态*/ if (1 == pISMartFrame->data[0]) { pitem->status |= 0x01; /*低1位*/ } if (1 == pISMartFrame->data[1]) { pitem->status |= 0x02; /*低2位*/ } if (1 == pISMartFrame->data[2]) { pitem->status |= 0x04; /*低3位*/ } if (1 == pISMartFrame->data[3]) { pitem->status |= 0x08; /*低4位*/ } /*时间*/ pitem->ntime = GetUptime(); return ReturnSuccess; }
int GetItemFromAny(ISmartFrame *pISMartFrame, Item *pitem) { /*mac*/ memcpy((void*)pitem->mac, &pISMartFrame->sourceMac[6], MAC_SIZE); /*类型*/ pitem->type = pISMartFrame->funCode.dev; /*状态*/ pitem->status = pISMartFrame->data[0]; /*时间*/ pitem->ntime = GetUptime(); return ReturnSuccess; }
int GetItemFromControlSocket(ISmartFrame *pISMartFrame, Item *pitem) { /*mac*/ memcpy((void*)pitem->mac, &pISMartFrame->sourceMac[6], MAC_SIZE); /*类型*/ pitem->type = pISMartFrame->funCode.dev; /*状态*/ if (1 == pISMartFrame->data[0]) { pitem->status |= 0x01; } /*时间*/ pitem->ntime = GetUptime(); return ReturnSuccess; }
int PackGatewayNodeRet(ISmartFrame *pISMartFrame, unsigned int *pnLen) { if (NULL == pISMartFrame || NULL == pnLen) { return ReturnError; } FillAA55(pISMartFrame); pISMartFrame->frameLength = htons(PACKAGE_SIZE_QUERYNODERET); pISMartFrame->dataLength = htons(PACKAGE_SIZE_QUERYNODERET - PACKAGE_SIZE_HEAD); *pnLen = PACKAGE_SIZE_QUERYNODERET; pISMartFrame->funCode.dev = PROTOCOL_TYPE_GATEWAY; pISMartFrame->funCode.ver = PROTOCOL_VERSION; pISMartFrame->funCode.fun = PROTOCOL_FUN_GATEWAY_QUERYNODERET; if (SourceMacNoInit == CheckInitSourceMac()) { return ReturnError; } FillSourceMac(pISMartFrame); FillSourceMacToTarget(pISMartFrame); FillCRC(pISMartFrame); PNode pnode = g_pNodeList->front; unsigned int i = 0; for (; pnode && i < 80; pnode = pnode->next, i++) { /*前四个字节直接填充*/ memcpy((void *)(pISMartFrame->data + 5 * i), (void *)(pnode->data), 4); /*第五个字节,需要用当前时间减去存储的时间,以获取时间差*/ long time = (char)(GetUptime() - ((Item *)(pnode->data))->ntime); if (time > 255) { time = 255; } *(pISMartFrame->data + 5*i + 4) = time; } return ReturnSuccess; }
/* ***************************************************************************** ** FUNCTION NAME: HttpRead ** ** FUNCTION INPUTS: ** @int fd: socket fd ** @int timeout: timeout (unit:seconds) e.g. 30 ** @PHTTP_RESPONSE pHttp: HTTP_RESPONSE struct for return ** ** FUNCTION DESCRIPTION ** This function will read http response from fd and package HTTP_RESPONSE. ** ** FUNCTION OUTPUTS: ** ZAPP_SUCCESS -> success ** ZAPP_TIMEOUT -> timeout ** ZAPP_FAILED -> other reason ** ** HISTORY: ** 2008-7-3 Steven Leong Created ***************************************************************************** */ int HttpRead(int fd, int timeout, PHTTP_RESPONSE pHttp) { Z_BUF zBuf; fd_set rdfds; struct timeval tv; char bufArray[BUF_16_BITS]; U32 lefttime, starttime, curtime; int n, nRet = ZAPP_SUCCESS; /* init */ FD_ZERO (&rdfds); FD_SET (fd, &rdfds); tv.tv_usec = 0; ZUtilBufInit(&zBuf, 0); lefttime = timeout; starttime = GetUptime(); memset(pHttp, 0, sizeof(HTTP_RESPONSE)); while(1) { tv.tv_sec = lefttime; select (fd+1, &rdfds, NULL, NULL, &tv); if(FD_ISSET (fd, &rdfds)){ memset(bufArray, 0, BUF_16_BITS); n = read(fd, bufArray, 1); //NOTE: This is very import!!! Don't remove. bufArray[n] = '\0'; /* Calculate lefttime */ if((curtime = GetUptime()) > 0){ lefttime -= curtime - starttime; starttime = curtime; } if(lefttime <= 0){ /* timeout */ nRet = ZAPP_TIMEOUT; goto appOut; } if(n < 0){ if( errno == EAGAIN) continue; else { /* pipe error */ dprintf("pipe error.\n"); nRet = ZAPP_FAILED; goto appOut; } } else if(n == 0){ /* The server close the socket */ //NOTE: we are reading the header. don't allow to close. */ dprintf("The server close the socket.\n"); nRet = ZAPP_FAILED; goto appOut; } //dprintf("Read Buf(%d)-> %s\n", n, bufArray); ZBufAttach(&zBuf, bufArray, n); /* Parse the header and choise parse content way */ if(strstr(zBuf.buf, HEADER_DCRLF)!= NULL){ dprintf(">>> Header buf-> %s\n", zBuf.buf); HttpPraseHeader(zBuf.buf,&pHttp->header); if(pHttp->header.transEncode == CHUNKED){ dprintf(">>> Parsing chunked content.\n"); nRet = ReadHttpContent(fd, &rdfds, lefttime, pHttp, 1); } else{ dprintf(">>> Parsing normal content.\n"); nRet = ReadHttpContent(fd, &rdfds, lefttime, pHttp, 0); } /* Return the result */ break; } } else{ /* timeout */ nRet = ZAPP_TIMEOUT; goto appOut; } } appOut: ZUtilBufDestroy(&zBuf); return nRet; }
/* ***************************************************************************** ** FUNCTION NAME: ReadHttpContent ** ** FUNCTION INPUTS: ** @int fd: fd ** @fd_set *prdfds: fd_set ** @int timeout: timeout ** @PHTTP_RESPONSE pHttp: ** @int chunked: 0=> not chunkd encoding, 1=> chunked encoding ** ** FUNCTION DESCRIPTION ** This function will read http content from fd and package HTTP_RESPONSE. ** ** FUNCTION OUTPUTS: ** ZAPP_SUCCESS -> success ** ZAPP_TIMEOUT -> timeout ** ZAPP_FAILED -> other reason ** ** HISTORY: ** 2008-7-11 Steven Leong Created ***************************************************************************** */ int ReadHttpContent(int fd, fd_set *prdfds, int timeout, PHTTP_RESPONSE pHttp, int chunked) { Z_BUF zBuf; struct timeval tv; char bufArray[BUF_1024_BITS]; U32 lefttime, starttime, curtime; int n, nRet = ZAPP_SUCCESS; //for chunked Z_BUF zBufChunk; char *ptr = NULL; int size; tv.tv_usec = 0; ZUtilBufInit(&zBuf, 0); ptr = &zBuf.buf[0]; lefttime = timeout; starttime = GetUptime(); while(1) { tv.tv_sec = lefttime; select (fd+1, prdfds, NULL, NULL, &tv); if(FD_ISSET (fd, prdfds)){ memset(bufArray, 0, BUF_1024_BITS); n = read(fd, bufArray, BUF_1024_BITS-1); /* Calculate lefttime */ if((curtime = GetUptime()) > 0){ lefttime -= curtime - starttime; starttime = curtime; } if(lefttime <= 0){ /* timeout */ nRet = ZAPP_TIMEOUT; goto appOut; } if(n < 0){ if( errno == EAGAIN) continue; else { /* pipe error */ dprintf("pipe error.\n"); nRet = ZAPP_FAILED; goto appOut; } } else if(n == 0){ /* The server close the socket */ //NOTE: we are reading the header. don't allow to close. */ dprintf("The server close the socket.\n"); if(chunked == 1) goto parseChunked; else goto readDone; } //dprintf("Read Buf(%d)-> %s\n", n, bufArray); ZBufAttach(&zBuf, bufArray, n); if(chunked == 1){ /* Chunked encoding */ //NOTE: "\r\n0\r\n" for end flag if(strstr(ptr, CRLF"0"CRLF) == NULL){ /* NOTE:zBuf.length-10 is very import. e.g. If former read is "xxxx\r", and this time is "\n0\r\n\r\n", it will make right.*/ if(zBuf.length > 10) ptr = &zBuf.buf[zBuf.length-10]; else ptr = &zBuf.buf[0]; } else goto parseChunked; } else{ /* Normal */ if(zBuf.length >= pHttp->header.contentLength) goto readDone; } } else{ /* timeout */ nRet = ZAPP_TIMEOUT; goto appOut; } } appOut: ZUtilBufDestroy(&zBuf); return nRet; readDone: //Done. Copy the content dprintf("Normal content Done.\n"); pHttp->contentSize = pHttp->header.contentLength; pHttp->content = zBuf.buf; zBuf.buf = NULL; ZUtilBufDestroy(&zBuf); return ZAPP_SUCCESS; parseChunked: dprintf("Chunk content done.\n"); ZUtilBufInit(&zBufChunk, 0); ptr = &zBuf.buf[0]; while(1){ //Try to find out the chunked length //NOTE: chunked is the Hex format n = sscanf(ptr, "%x"CRLF, &size); if(n <= 0 || size == 0) break; dprintf(">>>>>> ChunkSize:%d(%x)\n", size, size); pHttp->header.contentLength += size; ptr += GotoNextLine(ptr)+strlen(CRLF); ZBufAttach(&zBufChunk, ptr, size); ptr += (size+1); }; pHttp->header.contentLength = zBufChunk.length; pHttp->contentSize = pHttp->header.contentLength; pHttp->content = zBufChunk.buf; zBufChunk.buf = NULL; ZUtilBufDestroy(&zBufChunk); ZUtilBufDestroy(&zBuf); return ZAPP_SUCCESS; }
void CCommandProcessor::ParseCommand ( const char * const cmdBegin, const uint64_t currentTime ) { const char * const cmdEnd = SkipCharsNotInSet( cmdBegin, SPACE_AND_TAB ); assert( cmdBegin != cmdEnd ); const char * const paramBegin = SkipCharsInSet( cmdEnd, SPACE_AND_TAB ); bool extraParamsFound = false; if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_QUESTION_MARK, true, false, &extraParamsFound ) || IsCmd( cmdBegin, cmdEnd, CMDNAME_HELP, false, false, &extraParamsFound ) ) { PrintStr( "This console is similar to the Bus Pirate console." EOL ); PrintStr( "Commands longer than 1 character are case insensitive." EOL ); PrintStr( "WARNING: If a command takes too long to run, the watchdog may reset the board." EOL ); PrintStr( "Commands are:" EOL ); Printf( " %s, %s: Show this help text." EOL, CMDNAME_QUESTION_MARK, CMDNAME_HELP ); Printf( " %s: Show version information." EOL, CMDNAME_I ); Printf( " %s: Test USB transfer speed." EOL, CMDNAME_USBSPEEDTEST ); Printf( " %s: Show JTAG pin status (read as inputs)." EOL, CMDNAME_JTAGPINS ); Printf( " %s: Test JTAG shift speed. WARNING: Do NOT connect any JTAG device." EOL, CMDNAME_JTAGSHIFTSPEEDTEST ); Printf( " %s: Exercises malloc()." EOL, CMDNAME_MALLOCTEST ); Printf( " %s: Exercises C++ exceptions." EOL, CMDNAME_CPP_EXCEPTION_TEST ); Printf( " %s: Shows memory usage." EOL, CMDNAME_MEMORY_USAGE ); Printf( " %s" EOL, CMDNAME_CPU_LOAD ); Printf( " %s" EOL, CMDNAME_UPTIME ); Printf( " %s" EOL, CMDNAME_RESET ); Printf( " %s" EOL, CMDNAME_RESET_CAUSE ); Printf( " %s <addr> <byte count>" EOL, CMDNAME_PRINT_MEMORY ); Printf( " %s <milliseconds>" EOL, CMDNAME_BUSY_WAIT ); Printf( " %s <command|protocol>" EOL, CMDNAME_SIMULATE_ERROR ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_I, true, false, &extraParamsFound ) ) { #ifndef NDEBUG const char buildType[] = "Debug build"; #else const char buildType[] = "Release build"; #endif Printf( "JtagDue %s" EOL, PACKAGE_VERSION ); Printf( "%s, compiler version %s" EOL, buildType, __VERSION__ ); Printf( "Watchdog %s" EOL, ENABLE_WDT ? "enabled" : "disabled" ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_RESET, false, false, &extraParamsFound ) ) { // This message does not reach the other side, we would need to add some delay. // UsbPrint( txBuffer, "Resetting the board..." EOL ); __disable_irq(); // Note that this message always goes to the serial port console, // even if the user is connected over USB. It might be possible to send // it over USB and then wait for the outgoing buffer to be empty. SerialSyncWriteStr( "Resetting the board..." EOL ); SerialWaitForDataSent(); ResetBoard( ENABLE_WDT ); assert( false ); // We should never reach this point. return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_CPU_LOAD, false, false, &extraParamsFound ) ) { if ( ENABLE_CPU_SLEEP ) PrintStr( "CPU load statistics not available." EOL ); else DisplayCpuLoad(); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_UPTIME, false, false, &extraParamsFound ) ) { char buffer[ CONVERT_TO_DEC_BUF_SIZE ]; Printf( "Uptime: %s seconds." EOL, convert_unsigned_to_dec_th( GetUptime() / 1000, buffer, ',' ) ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_RESET_CAUSE, false, false, &extraParamsFound ) ) { DisplayResetCause(); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_PRINT_MEMORY, false, true, &extraParamsFound ) ) { PrintMemory( paramBegin ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_BUSY_WAIT, false, true, &extraParamsFound ) ) { BusyWait( paramBegin ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_USBSPEEDTEST, false, true, &extraParamsFound ) ) { ProcessUsbSpeedTestCmd( paramBegin, currentTime ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_JTAGPINS, false, false, &extraParamsFound ) ) { PrintJtagPinStatus(); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_JTAGSHIFTSPEEDTEST, false, false, &extraParamsFound ) ) { if ( !IsNativeUsbPort() ) throw std::runtime_error( "This command is only available on the 'Native' USB port." ); // Fill the Rx buffer with some test data. assert( m_rxBuffer != NULL ); m_rxBuffer->Reset(); for ( uint32_t i = 0; !m_rxBuffer->IsFull(); ++i ) { m_rxBuffer->WriteElem( CUsbRxBuffer::ElemType( i ) ); } // If the mode is set to MODE_HIZ, you cannot see the generated signal with the oscilloscope. // Note also that the built-in pull-ups on the Atmel ATSAM3X8 are too weak (between 50 and 100 KOhm, // yields too slow a rising time) to be of any use. const bool oldPullUps = GetJtagPullups(); SetJtagPullups( false ); const JtagPinModeEnum oldMode = GetJtagPinMode(); SetJtagPinMode ( MODE_JTAG ); // Each JTAG transfer needs 2 bits in the Rx buffer, TMS and TDI, // but produces only 1 bit, TDO. const uint32_t jtagByteCount = m_rxBuffer->GetElemCount() / 2; const uint16_t bitCount = jtagByteCount * 8; // Shift all JTAG data through several times. const uint64_t startTime = GetUptime(); const uint32_t iterCount = 50; for ( uint32_t i = 0; i < iterCount; ++i ) { // We hope that this will not clear the buffer contents. assert( m_rxBuffer != NULL ); assert( m_txBuffer != NULL ); m_rxBuffer->Reset(); m_rxBuffer->CommitWrittenElements( jtagByteCount * 2 ); m_txBuffer->Reset(); ShiftJtagData( m_rxBuffer, m_txBuffer, bitCount ); assert( m_txBuffer->GetElemCount() == jtagByteCount ); } const uint64_t finishTime = GetUptime(); const uint32_t elapsedTime = uint32_t( finishTime - startTime ); m_rxBuffer->Reset(); m_txBuffer->Reset(); const unsigned kBitsPerSec = unsigned( uint64_t(bitCount) * iterCount * 1000 / elapsedTime / 1024 ); SetJtagPinMode( oldMode ); SetJtagPullups( oldPullUps ); // I am getting 221 KiB/s with GCC 4.7.3 and optimisation level "-O3". Printf( EOL "Finished JTAG shift speed test, throughput %u Kbits/s (%u KiB/s)." EOL, kBitsPerSec, kBitsPerSec / 8 ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_MALLOCTEST, false, false, &extraParamsFound ) ) { PrintStr( "Allocalling memory..." EOL ); volatile uint32_t * const volatile mallocTest = (volatile uint32_t *) malloc(123); *mallocTest = 123; PrintStr( "Releasing memory..." EOL ); free( const_cast< uint32_t * >( mallocTest ) ); PrintStr( "Test finished." EOL ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_CPP_EXCEPTION_TEST, false, false, &extraParamsFound ) ) { try { PrintStr( "Throwing integer exception..." EOL ); throw 123; PrintStr( "Throw did not work." EOL ); assert( false ); } catch ( ... ) { PrintStr( "Caught integer exception." EOL ); } PrintStr( "Test finished." EOL ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_SIMULATE_ERROR, false, true, &extraParamsFound ) ) { SimulateError( paramBegin ); return; } if ( IsCmd( cmdBegin, cmdEnd, CMDNAME_MEMORY_USAGE, false, false, &extraParamsFound ) ) { const unsigned heapSize = unsigned( GetHeapEndAddr() - uintptr_t( &_end ) ); Printf( "Partitions: malloc heap: %u bytes, free: %u bytes, stack: %u bytes." EOL, heapSize, GetStackStartAddr() - GetHeapEndAddr(), STACK_SIZE ); Printf( "Used stack (estimated): %u from %u bytes." EOL, unsigned( GetStackSizeUsageEstimate() ), STACK_SIZE ); const struct mallinfo mi = mallinfo(); const unsigned heapSizeAccordingToNewlib = unsigned( mi.arena ); Printf( "Heap: %u allocated from %u bytes." EOL, unsigned( mi.uordblks ), unsigned( mi.arena ) ); assert( heapSize == heapSizeAccordingToNewlib ); UNUSED_IN_RELEASE( heapSizeAccordingToNewlib ); return; } if ( extraParamsFound ) Printf( "Command \"%.*s\" does not take any parameters." EOL, cmdEnd - cmdBegin, cmdBegin ); else Printf( "Unknown command \"%.*s\"." EOL, cmdEnd - cmdBegin, cmdBegin ); }