uint8_t tcp_socket_init(TCP_CONFIG *config) { static bool startup=false; if(!startup) { GPIO_Configuration(); Reset_W5200(); WIZ_SPI_Init(); Set_network(config->Source_IP, config->Gateway, config->MAC, config->Subnet); startup=true; while (getSn_SR(config->s) != SOCK_CLOSED); } if(socket(config->s,Sn_MR_TCP,config->Source_Port,0x00)== 0) /* reinitialize the socket */ { return 0; //TCP socket failed } while (getSn_SR(config->s) != SOCK_INIT); // Wait for socket to open IINCHIP_WRITE(Sn_CR(config->s), Sn_CR_LISTEN); // Start listening on port specified while (IINCHIP_READ(Sn_CR(config->s))); // Check status while (getSn_SR(config->s) != SOCK_LISTEN); // Wait for listen return 1; }
uint8_t process_request(TCP_CONFIG *config) { uint16_t bytes_to_send =0; uint8_t rets=0; if(bytesReceived>tcp_data_buffer_size) return 0; // Content overflow // Assuming GIT request, read and parse if you with to use urls for anything recv_data_processing(config->s, tcp_data_buffer, bytesReceived); // Data from the GIT request sprintf(website,"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n\ <html>\n<head>\n<center><h1>%d</h1></center>\n<meta http-equiv=\"refresh\" content=\"1.5\" >",ADCRead(0)); bytes_to_send = strlen((char *)website); rets = send(config->s, website,bytes_to_send , 0); // Send Response with html bytesReceived=0; IINCHIP_WRITE(Sn_CR(config->s), Sn_CR_DISCON); // Shut down connection while (IINCHIP_READ(Sn_CR(config->s))); // IINCHIP_WRITE(Sn_CR(config->s), Sn_CR_CLOSE); // while (IINCHIP_READ(Sn_CR(config->s))); // IINCHIP_WRITE(Sn_IR(config->s), 0xFF); // return 1; }
/** @brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer. @return 1 for success else 0. */ uint8 listen( SOCKET s /**< the socket number */ ) { uint8 ret; #ifdef __DEF_IINCHIP_DBG__ printf("listen()\r\n"); #endif if (wiz_read_byte(Sn_SR(s)) == SOCK_INIT) { wiz_write_byte(Sn_CR(s),Sn_CR_LISTEN); /* +20071122[chungs]:wait to process the command... */ while( wiz_read_byte(Sn_CR(s)) ) ; /* ------- */ ret = 1; } else { ret = 0; #ifdef __DEF_IINCHIP_DBG__ printf("Fail[invalid ip,port]\r\n"); #endif } return ret; }
/** @brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it. @return 1 for sucess else 0. */ uint8 socket( SOCKET s, /**< for socket number */ uint8 protocol, /**< for socket protocol */ uint16 port, /**< the source port for the socket */ uint8 flag /**< the option for the socket */ ) { uint8 ret; #ifdef __DEF_IINCHIP_DBG__ printf("socket()\r\n"); #endif if ((protocol == Sn_MR_TCP) || (protocol == Sn_MR_UDP) || (protocol == Sn_MR_IPRAW) || (protocol == Sn_MR_MACRAW) || (protocol == Sn_MR_PPPOE)) { close(s); if (!port) port = local_port++; wiz_write_byte(Sn_MR(s),protocol | flag); // if don't set the source port, set local_port number. wiz_write_word(Sn_PORT0(s),port); wiz_write_byte(Sn_CR(s),Sn_CR_OPEN); // run sockinit Sn_CR /* +20071122[chungs]:wait to process the command... */ while( wiz_read_byte(Sn_CR(s)) ) ; /* ------- */ ret = 1; } else { ret = 0; } #ifdef __DEF_IINCHIP_DBG__ printf("Sn_SR = %.2x , Protocol = %.2x\r\n", wiz_read_byte(Sn_SR(s)), wiz_read_byte(Sn_MR(s))); #endif return ret; }
/** @brief This function established the connection for the channel in Active (client) mode. This function waits for the untill the connection is established. @return 1 for success else 0. */ uint8 connect(SOCKET s, uint8 * addr, uint16 port) { uint8 ret; #ifdef __DEF_IINCHIP_DBG__ printf("connect()\r\n"); #endif if ( ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) || ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || (port == 0x00) ) { ret = 0; #ifdef __DEF_IINCHIP_DBG__ printf("Fail[invalid ip,port]\r\n"); #endif } else { ret = 1; // set destination IP wiz_write_buf(Sn_DIPR0(s), addr,4); wiz_write_word(Sn_DPORT0(s),port); wiz_write_byte(Sn_CR(s),Sn_CR_CONNECT); /* m2008.01 [bj] : wait for completion */ while ( wiz_read_byte(Sn_CR(s)) ) ; } return ret; }
/** @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 关闭网络 *@return 无 */ void CloseSocket_RJ45_2(void) { u8 i; RJ45_2_Write_Register(Sn_CR(0),Sn_CR_CLOSE); for(i=0;i<20;i++); while(RJ45_2_Read_Register(Sn_CR(0))) /*Wait to process the command*/ { for(i=0;i<20;i++); } RJ45_2_Write_Register(Sn_IR(0),0xFF); /*All clear*/ }
/** *@brief TCP模式初始化 客户端 默认连接三次,三次连接不上,返回Fail *@param 无 *@return 无 */ u8 RJ45_1_TCP_ClientInit(void) { u8 i,j=0; RJ45_1_Write_Register(SIMR,1<<0); //允许SOCKET0产生中断 RJ45_1_Write_Register(Sn_IMR(0) ,Sn_IR_RECV|Sn_IR_DISCON|Sn_IR_CON); //设置中断屏蔽寄存器 CloseSocket_RJ45_1(); RJ45_1_Write_Register(Sn_MR(0),Sn_MR_TCP|Sn_MR_ND); //tcp模式,无延时 WriteTem[0]=RJ45_1_Loc_Potr/256; WriteTem[1]=RJ45_1_Loc_Potr%256; RJ45_1_Write_Buf(Sn_PORT0(0),WriteTem,2); //设置端口号 WriteTem[0]=RJ45_1_Dir_Port/256; WriteTem[1]=RJ45_1_Dir_Port%256; RJ45_1_Write_Buf(Sn_DPORT0(0),WriteTem,2); //设置目标服务器端口号 RJ45_1_Write_Buf(Sn_DIPR0(0),RJ45_1_DirIP,4); //目标服务器IP地址 RJ45_1_Write_Register(Sn_KPALVTR(0),1); //每5s自动检测一次连接状态 Init1: RJ45_1_Write_Register(Sn_CR(0),Sn_CR_OPEN); for(i=0;i<20;i++); while(RJ45_1_Read_Register(Sn_CR(0))) /*Wait to process the command*/ { for(i=0;i<20;i++); } if(RJ45_1_Read_Register(Sn_SR(0))!=SOCK_INIT) //检测网口开启状态 { j++; if(j<10) { CloseSocket_RJ45_1(); goto Init1; } else { CloseSocket_RJ45_1(); return Fail; } } RJ45_1_Write_Register(Sn_CR(0),Sn_CR_CONNECT); //开启连接 RJ45_1_Read_Buf(Sn_DIPR0(0),RJ45_1_DirIP,4); while(RJ45_1_Read_Register(Sn_CR(0))) /*Wait to process the command*/ { } while(RJ45_1_Read_Register(Sn_SR(0))!=SOCK_SYNSENT) { if(RJ45_1_Read_Register(Sn_SR(0))==SOCK_ESTABLISHED) { return Success; } if(RJ45_1_Read_Register(Sn_IR(0))& Sn_IR_TIMEOUT) { RJ45_1_Write_Register(Sn_IR(0),Sn_IR_TIMEOUT); return Fail; } } }
/** @brief This function used for disconnect the socket and parameter is "s" which represent the socket number @return 1 for success else 0. */ void disconnect(SOCKET s) { #ifdef __DEF_IINCHIP_DBG__ printf("disconnect()\r\n"); #endif wiz_write_byte(Sn_CR(s),Sn_CR_DISCON); /* +20071122[chungs]:wait to process the command... */ while( wiz_read_byte(Sn_CR(s)) ) ; /* ------- */ }
/** *@brief 发送数据 *@param WData:发送数组 *@param Len: 发送数据长度,Len<=8K *@return 无 */ void RJ45_2_Write(u8 *WData,u16 Len) { u16 Start_Address; u32 Address; RJ45_2_Read_Buf(Sn_TX_WR0(0),ReadTem,2); Start_Address=ReadTem[0]*256+ReadTem[1]; //获取写入地址指针 Address=(u32)(Start_Address<<8)+(0<<5)+0x10; //计算绝对地址 RJ45_2_Write_Buf(Address,WData,Len); //写入缓存 Start_Address+=Len; WriteTem[0]=Start_Address/256; WriteTem[1]=Start_Address%256; RJ45_2_Write_Buf(Sn_TX_WR0(0),WriteTem,2); //更新指针 RJ45_2_Write_Register(Sn_CR(0),Sn_CR_SEND); //发送 while(RJ45_2_Read_Register(Sn_CR(0))); /*Wait to process the command*/ }
/** *@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*/ }
//TCP模式初始化 服务器 u8 RJ45_2_TCP_ServiceInit(void) { u8 i,j=0; RJ45_2_Write_Register(SIMR,1<<0); //允许SOCKET0产生中断 RJ45_2_Write_Register(Sn_IMR(0) ,Sn_IR_RECV|Sn_IR_TIMEOUT|Sn_IR_DISCON|Sn_IR_CON); //设置中断屏蔽寄存器 CloseSocket_RJ45_2(); RJ45_2_Write_Register(Sn_MR(0),Sn_MR_TCP|Sn_MR_ND); //tcp模式,无延时 WriteTem[0]=RJ45_2_Loc_Potr/256; WriteTem[1]=RJ45_2_Loc_Potr%256; RJ45_2_Write_Buf(Sn_PORT0(0),WriteTem,2); //设置端口号 RJ45_2_Write_Register(Sn_KPALVTR(0),1); //每5s自动检测一次连接状态 Init1: RJ45_2_Write_Register(Sn_CR(0),Sn_CR_OPEN); for(i=0;i<20;i++); while(RJ45_2_Read_Register(Sn_CR(0))) /*Wait to process the command*/ { for(i=0;i<20;i++); } if(RJ45_2_Read_Register(Sn_SR(0))!=SOCK_INIT) //检测网口开启状态 { j++; if(j<10) { CloseSocket_RJ45_2(); goto Init1; } else { CloseSocket_RJ45_2(); return Fail; } } RJ45_2_Write_Register(Sn_CR(0),Sn_CR_LISTEN); //开启监听状态 for(i=0;i<20;i++); while(RJ45_2_Read_Register(Sn_CR(0))) /*Wait to process the command*/ { for(i=0;i<20;i++); } return Success; }
/** @brief This function close the socket and parameter is "s" which represent the socket number */ void close(SOCKET s) { #ifdef __DEF_IINCHIP_DBG__ printf("close()\r\n"); #endif wiz_write_byte(Sn_CR(s),Sn_CR_CLOSE); /* +20071122[chungs]:wait to process the command... */ while( wiz_read_byte(Sn_CR(s)) ) ; /* ------- */ /* +2008.01 [hwkim]: clear interrupt */ #ifdef __DEF_IINCHIP_INT__ /* m2008.01 [bj] : all clear */ putISR(s, 0x00); #else /* m2008.01 [bj] : all clear */ wiz_write_byte(Sn_IR(s), 0xFF); #endif }
// 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; }
uint8 getSn_CR(SOCKET s) { return IINCHIP_READ(Sn_CR(s)); }
void setSn_CR(SOCKET s, uint16 com) { IINCHIP_WRITE(Sn_CR(s),com); while(IINCHIP_READ(Sn_CR(s))); // wait until Sn_CR is cleared. }
// return value: // A DNSError_t (DNSSuccess on success, something else otherwise) // in "int" mode: positive on success, negative on error DNSError_t EthernetDNSClass::_sendDNSQueryPacket(const char* hostName) { DNSError_t statusCode = DNSSuccess; uint16_t ptr = 0; #if defined(_USE_MALLOC_) DNSHeader_t* dnsHeader = NULL; #else DNSHeader_t dnsHeaderBuf; DNSHeader_t* dnsHeader = &dnsHeaderBuf; #endif const char* p1, *p2; char* p3; uint8_t* buf; int c, i, bsize, len; if (NULL == hostName || 0 == *hostName) { statusCode = DNSInvalidArgument; goto errorReturn; } ptr = IINCHIP_READ(Sn_TX_WR0(this->_socket)); ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_TX_WR0(this->_socket) + 1); #if defined(_USE_MALLOC_) dnsHeader = (DNSHeader_t*)malloc(sizeof(DNSHeader_t)); if (NULL == dnsHeader) { statusCode = DNSOutOfMemory; goto errorReturn; } #endif memset(dnsHeader, 0, sizeof(DNSHeader_t)); dnsHeader->xid = dns_htons(++this->_dnsData.xid); dnsHeader->recursionDesired = 1; dnsHeader->queryCount = dns_htons(1); dnsHeader->opCode = DNSOpQuery; write_data(this->_socket, (vuint8*)dnsHeader, (vuint8*)ptr, sizeof(DNSHeader_t)); ptr += sizeof(DNSHeader_t); p1 = hostName; bsize = sizeof(DNSHeader_t); buf = (uint8_t*)dnsHeader; while(*p1) { c = 1; p2 = p1; while (0 != *p2 && '.' != *p2) { p2++; c++; }; p3 = (char*)buf; i = c; len = bsize-1; *p3++ = (uint8_t)--i; while (i-- > 0) { *p3++ = *p1++; if (--len <= 0) { write_data(this->_socket, (vuint8*)buf, (vuint8*)ptr, bsize); ptr += bsize; len = bsize; p3 = (char*)buf; } } while ('.' == *p1) ++p1; if (len != bsize) { write_data(this->_socket, (vuint8*)buf, (vuint8*)ptr, bsize-len); ptr += bsize-len; } } // first byte is the query string's zero termination, then qtype and class follow. buf[0] = buf[1] = buf[3] = 0; buf[2] = buf[4] = 1; write_data(this->_socket, (vuint8*)buf, (vuint8*)ptr, 5); ptr += 5; IINCHIP_WRITE(Sn_TX_WR0(this->_socket), (vuint8)((ptr & 0xff00) >> 8)); IINCHIP_WRITE((Sn_TX_WR0(this->_socket) + 1), (vuint8)(ptr & 0x00ff)); IINCHIP_WRITE(Sn_CR(this->_socket), Sn_CR_SEND); while(IINCHIP_READ(Sn_CR(this->_socket))); if (_state == DNSStateIdle) { this->_dnsData.lastQueryFirstXid = this->_dnsData.xid; } this->_state = DNSStateQuerySent; statusCode = DNSSuccess; errorReturn: this->_lastSendMillis = millis(); #if defined(_USE_MALLOC_) if (NULL != dnsHeader) free(dnsHeader); #endif return statusCode; }