/** @brief This function is an application I/F function which is used to receive the data in other then TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well. @return This function return received data size for success else -1. */ uint16 recvfrom( SOCKET s, /**< the socket number */ uint8 * buf, /**< a pointer to copy the data to be received */ uint16 len, /**< the data size to read */ uint8 * addr, /**< a pointer to store the peer's IP address */ uint16 *port /**< a pointer to store the peer's port number. */ ) { uint8 head[8]; uint16 data_len=0; uint16 ptr=0; if ( len > 0 ) { ptr = wiz_read_word(Sn_RX_RD0(s)); switch (wiz_read_byte(Sn_MR(s)) & 0x07) { case Sn_MR_UDP : read_data(s, (uint8 *)ptr, head, 0x08); ptr += 8; // read peer's IP address, port number. addr[0] = head[0]; addr[1] = head[1]; addr[2] = head[2]; addr[3] = head[3]; *port = (head[4] << 8) + head[5]; data_len = (head[6] << 8) + head[7]; break; case Sn_MR_IPRAW : read_data(s, (uint8 *)ptr, head, 0x06); ptr += 6; addr[0] = head[0]; addr[1] = head[1]; addr[2] = head[2]; addr[3] = head[3]; data_len = (head[4] << 8) + head[5]; break; case Sn_MR_MACRAW : read_data(s, (uint8 *)ptr, head, 2); ptr += 2; data_len = (head[0]<<8) + head[1] - 2; break; default : break; } read_data(s,(uint8*) ptr,buf,data_len); // Does nothing if data_len = 0 ptr += data_len; wiz_write_word(Sn_RX_RD0(s),ptr); wiz_write_byte(Sn_CR(s),Sn_CR_RECV); while( wiz_read_byte(Sn_CR(s)) ) ; } return data_len; }
/** *@brief 读取数据 *@param RData:读取数据存放数组 *@return 无 */ void RJ45_2_Read(u8 *RData) { u16 Start_Address; u32 Address; RJ45_2_Read_Buf(Sn_RX_RSR0(0),ReadTem,2); RJ45_2_RLength =ReadTem[0]*256+ReadTem[1]; //获取接收到数据长度 RJ45_2_Read_Buf(Sn_RX_RD0(0),ReadTem,2); Start_Address=ReadTem[0]*256+ReadTem[1]; //获取相对地址 WriteTem[0]=(Start_Address+RJ45_2_RLength)/256; WriteTem[1]=(Start_Address+RJ45_2_RLength)%256; Address=(u32)(Start_Address<<8)+(0<<5)+0x18; //得到绝对地址 RJ45_2_Read_Buf(Address,RData,RJ45_2_RLength); //读取数据 RJ45_2_Write_Buf(Sn_RX_RD0(0),WriteTem,2); //写入读取指针 RJ45_2_Write_Register(Sn_CR(0),Sn_CR_RECV); while(RJ45_2_Read_Register(Sn_CR(0))); /*Wait to process the command*/ }
// return value: // A DNSError_t (DNSSuccess on success, something else otherwise) // in "int" mode: positive on success, negative on error DNSError_t EthernetDNSClass::pollDNSReply(byte ipAddr[4]) { DNSError_t statusCode = DNSSuccess; #if defined(_USE_MALLOC_) DNSHeader_t* dnsHeader = NULL; #else DNSHeader_t dnsHeaderBuf; DNSHeader_t* dnsHeader = &dnsHeaderBuf; #endif uint8_t* buf; uint32_t svr_addr; uint16_t svr_port, udp_len, ptr, qCnt, aCnt; if (DNSStateQuerySent != this->_state) { statusCode = DNSNothingToDo; goto errorReturn; } if (NULL == ipAddr) { statusCode = DNSInvalidArgument; goto errorReturn; } if (0 == (IINCHIP_READ(Sn_RX_RSR0(this->_socket))) && 0 == (IINCHIP_READ(Sn_RX_RSR0(this->_socket) + 1))) { statusCode = DNSTryLater; goto errorReturn; } #if defined(_USE_MALLOC_) dnsHeader = (DNSHeader_t*)malloc(sizeof(DNSHeader_t)); if (NULL == dnsHeader) { statusCode = DNSOutOfMemory; goto errorReturn; } #endif ptr = IINCHIP_READ(Sn_RX_RD0(this->_socket)); ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_RX_RD0(this->_socket) + 1); // read UDP header buf = (uint8_t*)dnsHeader; read_data(this->_socket, (vuint8*)ptr, (vuint8*)buf, 8); ptr += 8; memcpy(&svr_addr, buf, sizeof(uint32_t)); *((uint16_t*)&svr_port) = dns_ntohs(*((uint32_t*)(buf+4))); *((uint16_t*)&udp_len) = dns_ntohs(*((uint32_t*)(buf+6))); read_data(this->_socket, (vuint8*)ptr, (vuint8*)dnsHeader, sizeof(DNSHeader_t)); if (0 != dnsHeader->responseCode) { if (3 == dnsHeader->responseCode) statusCode = DNSNotFound; else statusCode = DNSServerError; goto errorReturn; } dnsHeader->xid = dns_ntohs(dnsHeader->xid); qCnt = dns_ntohs(dnsHeader->queryCount); aCnt = dns_ntohs(dnsHeader->answerCount); if (dnsHeader->queryResponse && DNSOpQuery == dnsHeader->opCode && DNS_SERVER_PORT == svr_port && this->_dnsData.lastQueryFirstXid <= dnsHeader->xid && this->_dnsData.xid >= dnsHeader->xid && 0 == memcmp(&svr_addr, this->_dnsData.serverIpAddr, sizeof(uint32_t))) { statusCode = DNSServerError; // if we don't find our A record answer, the server messed up. int i, offset = sizeof(DNSHeader_t); uint8_t* buf = (uint8_t*)dnsHeader; int rLen; // read over the query section and answer section, stop on the first a record for (i=0; i<qCnt+aCnt; i++) { do { read_data(this->_socket, (vuint8*)(ptr+offset), (vuint8*)buf, 1); rLen = buf[0]; if (rLen > 128) // handle DNS name compression offset += 2; else offset += rLen + 1; } while (rLen > 0 && rLen <= 128); // if this is an answer record, there are more fields to it. if (i >= qCnt) { read_data(this->_socket, (vuint8*)(ptr+offset), (vuint8*)buf, 4); offset += 8; // skip over the 4-byte TTL field read_data(this->_socket, (vuint8*)(ptr+offset), (vuint8*)&buf[4], 2); offset += 2; // if class and qtype match, and data length is 4, this is an IP address, and // we're done. if (1 == buf[1] && 1 == buf[3] && 4 == buf[5]) { read_data(this->_socket, (vuint8*)(ptr+offset), (vuint8*)ipAddr, 4); statusCode = DNSSuccess; break; } } else offset += 4; // eat the query type and class fields of a query } } ptr += udp_len; IINCHIP_WRITE(Sn_RX_RD0(this->_socket),(vuint8)((ptr & 0xff00) >> 8)); IINCHIP_WRITE((Sn_RX_RD0(this->_socket) + 1),(vuint8)(ptr & 0x00ff)); IINCHIP_WRITE(Sn_CR(this->_socket),Sn_CR_RECV); while(IINCHIP_READ(Sn_CR(this->_socket))); errorReturn: if (DNSTryLater == statusCode) { unsigned long now = millis(); if (now - this->_lastSendMillis > DNS_TIMEOUT_MILLIS || now < this->_lastSendMillis) { this->_state = DNSStateIdle; statusCode = DNSTimedOut; } } else { this->_closeDNSSession(); this->_state = DNSStateIdle; } #if defined(_USE_MALLOC_) if (NULL != dnsHeader) free(dnsHeader); #endif return statusCode; }