//******************************************************************************************* // // Function : arp_who_is // Description : send arp request to destination ip, and save destination mac to dest_mac. // call this function to find the destination mac address before send other packet. // //******************************************************************************************* BYTE arp_who_is ( BYTE *rxtx_buffer, BYTE *dest_mac, BYTE *dest_ip ) { BYTE i; WORD dlength; // send arp request packet to network arp_send_request ( rxtx_buffer, dest_ip ); for ( i=0; i<10; i++ ) { // Time out 10x10ms = 100ms _delay_ms ( 10 ); dlength = enc28j60_packet_receive( rxtx_buffer, MAX_RXTX_BUFFER ); // destination ip address was found on network if ( dlength ) { if ( arp_packet_is_arp ( rxtx_buffer, (WORD_BYTES){ARP_OPCODE_REPLY_V} ) ) { // copy destination mac address from arp reply packet to destination mac address memcpy ( dest_mac, &rxtx_buffer[ ETH_SRC_MAC_P ], sizeof(MAC_ADDR) ); return 1; } } } // destination ip was not found on network return 0; }
//***************************************************************************************** // // Function : server_process // Description : Run web server and listen on port 80 // //***************************************************************************************** void server_process ( void ) { MAC_ADDR client_mac; IP_ADDR client_ip; // you can change rx,tx buffer size in includes.h BYTE rxtx_buffer[MAX_RXTX_BUFFER]; WORD plen; if ( flag1.bits.syn_is_sent ) return; // get new packet plen = enc28j60_packet_receive( (BYTE*)&rxtx_buffer, MAX_RXTX_BUFFER ); //plen will ne unequal to zero if there is a valid packet (without crc error) if(plen==0) return; // copy client mac address from buffer to client mac variable memcpy ( (BYTE*)&client_mac, &rxtx_buffer[ ETH_SRC_MAC_P ], sizeof(MAC_ADDR) ); // check arp packet if match with avr ip let's send reply if ( arp_packet_is_arp( rxtx_buffer, (WORD_BYTES){ARP_OPCODE_REQUEST_V} ) ) { arp_send_reply ( (BYTE*)&rxtx_buffer, (BYTE*)&client_mac ); return; } // get client ip address memcpy ( (BYTE*)&client_ip, &rxtx_buffer[ IP_SRC_IP_P ], sizeof(IP_ADDR) ); // check ip packet send to avr or not? if ( ip_packet_is_ip ( (BYTE*)&rxtx_buffer ) == 0 ) { return; } // check packet if packet is icmp packet let's send icmp echo reply if ( icmp_send_reply ( (BYTE*)&rxtx_buffer, (BYTE*)&client_mac, (BYTE*)&client_ip ) ) { return; } // start web server at port 80, see http.c http_webserver_process ( (BYTE*)rxtx_buffer, (BYTE*)&client_mac, (BYTE*)&client_ip ); }
//***************************************************************************************** // // Function : client_process // Description : send temparature to web server, this option is disabled by default. // YOU MUST install webserver and server script before enable this option, // I recommented Apache webserver and PHP script. // More detail about Apache and PHP installation please visit http://www.avrportal.com/ // //***************************************************************************************** void client_process ( void ) { WORD dlength; // you can change rx,tx buffer size in includes.h BYTE rxtx_buffer[MAX_RXTX_BUFFER]; // wait for send temparature flag is set, this flag set by time_base function (menu.c) if ( flag1.bits.send_temp == 0 ) return; // AVR busy now and wait untill transfer data to web browser completed. if ( flag1.bits.syn_is_received ) return; // AVR sent temparature to web server but not found web server on port 80 //if ( flag1.bits.not_found_server ) // return; // send SYN to initial connection if ( flag1.bits.syn_is_sent == 0 ) { // start arp // server ip was not found on network if ( arp_who_is ( rxtx_buffer, (BYTE*)&server_mac, (BYTE*)&server_ip ) == 0 ) { flag1.bits.send_temp = 0; return; } // send SYN packet to initial connection tcp_send_packet ( rxtx_buffer, (WORD_BYTES){80}, // destination port (WORD_BYTES){1200}, // source port TCP_FLAG_SYN_V, // flag 1, // (bool)maximum segment size 1, // (bool)clear sequence ack number 0, // 0=use old seq, seqack : 1=new seq,seqack no data : new seq,seqack with data 0, // tcp data length (BYTE*)&server_mac, // server mac address (BYTE*)&server_ip ); // server ip address flag1.bits.syn_is_sent = 1; } // get new packet dlength = enc28j60_packet_receive( (BYTE*)&rxtx_buffer, MAX_RXTX_BUFFER ); // no new packet incoming if ( dlength == 0 ) { // timeout occured, when SYN has been sent but no response from web server // reset send_temp and syn_is_sent flags if ( flag1.bits.send_temp_timeout ) { flag1.bits.send_temp_timeout = 0; flag1.bits.send_temp = 0; flag1.bits.syn_is_sent = 0; } return; } // check ip packet send to avr or not? // accept ip packet only if ( ip_packet_is_ip ( (BYTE*)&rxtx_buffer ) == 0 ) { return; } // check SYNACK flag, after AVR send SYN server response by send SYNACK to AVR if ( rxtx_buffer [ TCP_FLAGS_P ] == ( TCP_FLAG_SYN_V | TCP_FLAG_ACK_V ) ) { // send ACK to answer SYNACK tcp_send_packet ( (BYTE*)&rxtx_buffer, (WORD_BYTES){80}, // destination port (WORD_BYTES){1200}, // source port TCP_FLAG_ACK_V, // flag 0, // (bool)maximum segment size 0, // (bool)clear sequence ack number 1, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data 0, // tcp data length (BYTE*)&server_mac, // server mac address (BYTE*)&server_ip ); // server ip address // setup http request to server dlength = http_put_request( (BYTE*)&rxtx_buffer ); // send http request packet // send packet with PSHACK tcp_send_packet ( (BYTE*)&rxtx_buffer, (WORD_BYTES){80}, // destination port (WORD_BYTES){1200}, // source port TCP_FLAG_ACK_V | TCP_FLAG_PSH_V, // flag 0, // (bool)maximum segment size 0, // (bool)clear sequence ack number 0, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data dlength, // tcp data length (BYTE*)&server_mac, // server mac address (BYTE*)&server_ip ); // server ip address return; } // after AVR send http request to server, server response by send data with PSHACK to AVR // AVR answer by send ACK and FINACK to server if ( rxtx_buffer [ TCP_FLAGS_P ] == (TCP_FLAG_ACK_V|TCP_FLAG_PSH_V) ) { dlength = tcp_get_dlength( (BYTE*)&rxtx_buffer ); // send ACK to answer PSHACK from server tcp_send_packet ( (BYTE*)&rxtx_buffer, (WORD_BYTES){80}, // destination port (WORD_BYTES){1200}, // source port TCP_FLAG_ACK_V, // flag 0, // (bool)maximum segment size 0, // (bool)clear sequence ack number dlength, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data 0, // tcp data length (BYTE*)&server_mac, // server mac address (BYTE*)&server_ip ); // server ip address // send finack to disconnect from web server tcp_send_packet ( (BYTE*)&rxtx_buffer, (WORD_BYTES){80}, // destination port (WORD_BYTES){1200}, // source port TCP_FLAG_FIN_V|TCP_FLAG_ACK_V, // flag 0, // (bool)maximum segment size 0, // (bool)clear sequence ack number 0, // (bool)calculate new seq and seqack number 0, // tcp data length (BYTE*)&server_mac, // server mac address (BYTE*)&server_ip ); // server ip address return; //menu_flag.bits.send_temp = 0; //send_syn = 0; } // answer FINACK from web server by send ACK to web server if ( rxtx_buffer [ TCP_FLAGS_P ] == (TCP_FLAG_FIN_V|TCP_FLAG_ACK_V) ) { // send ACK with seqack = 1 tcp_send_packet ( (BYTE*)&rxtx_buffer, (WORD_BYTES){80}, // destination port (WORD_BYTES){1200}, // source port TCP_FLAG_ACK_V, // flag 0, // (bool)maximum segment size 0, // (bool)clear sequence ack number 1, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data 0, // tcp data length (BYTE*)&server_mac, // server mac address (BYTE*)&server_ip ); // server ip address // temparature has been sent // and wait for next schedule to send temparature flag1.bits.send_temp = 0; flag1.bits.syn_is_sent = 0; } }