Exemple #1
0
// Perform all processing to get an IP address plus other addresses returned, e.g. gw, dns, dhcp server.
// Returns 1 for successful IP address allocation, 0 otherwise
uint8_t EtherShield::allocateIPAddress(uint8_t *buf, uint16_t buffer_size, uint8_t *mymac, uint16_t myport, uint8_t *myip, uint8_t *mynetmask, uint8_t *gwip, uint8_t *dnsip, uint8_t *dhcpsvrip ) {
  uint16_t dat_p;
  int plen = 0;
  long lastDhcpRequest = millis();
  uint8_t dhcpState = 0;
  boolean gotIp = false;
  uint8_t dhcpTries = 10;	// After 10 attempts fail gracefully so other action can be carried out

  dhcp_start( buf, mymac, myip, mynetmask,gwip, dnsip, dhcpsvrip );

  while( !gotIp ) {
    // handle ping and wait for a tcp packet
    plen = enc28j60PacketReceive(buffer_size, buf);
    dat_p=packetloop_icmp_tcp(buf,plen);
    if(dat_p==0) {
      int retstat = check_for_dhcp_answer( buf, plen);
      dhcpState = dhcp_state();
      // we are idle here
      if( dhcpState != DHCP_STATE_OK ) {
        if (millis() > (lastDhcpRequest + 10000L) ){
          lastDhcpRequest = millis();
	  if( --dhcpTries <= 0 ) 
		  return 0;		// Failed to allocate address
          // send dhcp
          dhcp_start( buf, mymac, myip, mynetmask,gwip, dnsip, dhcpsvrip );
        }
      } else {
        if( !gotIp ) {
          gotIp = true;

          //init the ethernet/ip layer:
          init_ip_arp_udp_tcp(mymac, myip, myport);

          // Set the Router IP
          client_set_gwip(gwip);  // e.g internal IP of dsl router

          // Set the DNS server IP address if required, or use default
          dnslkup_set_dnsip( dnsip );

        }
      }
    }
  }

  return 1;

}
void EtherShield::ES_client_set_gwip(uint8_t *gwipaddr) {
	client_set_gwip(gwipaddr);
}
int main(void){

        
        uint16_t dat_p,plen;
        int8_t cmd;
        
        // Set the clock speed to "no pre-scaler" (8MHz with internal osc or 
        // full external speed)
        // set the clock prescaler. First write CLKPCE to enable setting 
        // of clock the next four instructions.
        // Note that the CKDIV8 Fuse determines the initial
        // value of the CKKPS bits.
        CLKPR=(1<<CLKPCE); // change enable
        CLKPR=0; // "no pre-scaler"
        _delay_loop_1(0); // 60us


        /*initialize enc28j60*/
        enc28j60Init(mymac);
        enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
        _delay_loop_1(0); // 60us
        
        /* Magjack leds configuration, see enc28j60 datasheet, page 11 */
        // LEDB=yellow LEDA=green
        //
        // 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
        // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10);
        enc28j60PhyWrite(PHLCON,0x476);
        
        DDRB|= (1<<DDB1); // LED, enable PB1, LED as output
        LEDOFF;

        DDRD&= ~(1<<DDD6); // enable PB6, as input
        PORTD|= (1<<PIND6); // internal pullup resistor on

        init_cnt2();
        sei();

        //init the web server ethernet/ip layer:
        init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT);
        // init the web client:
        client_set_gwip(gwip);  // e.g internal IP of dsl router
        //
        while(1){
                // handle ping and wait for a tcp packet
                plen=enc28j60PacketReceive(BUFFER_SIZE, buf);
                dat_p=packetloop_icmp_tcp(buf,plen);
                if(plen==0){
                        // we are idle here
                        if (client_waiting_gw() ){
                                continue;
                        }
                        if (dns_state==0){
                                sec=0;
                                dns_state=1;
                                dnslkup_request(buf,PSTR(WEBSERVER_VHOST));
                                continue;
                        }
                        if (dns_state==1 && dnslkup_haveanswer()){
                                dns_state=2;
                                client_set_wwwip(dnslkup_getip());
                        }
                        if (dns_state!=2){
                                // retry every minute if dns-lookup failed:
                                if (sec > 60){
                                        dns_state=0;
                                }
                                // don't try to use web client before
                                // we have a result of dns-lookup
                                continue;
                        }
                        //----------
                        if (start_web_client==1){
                                LEDON;
                                start_web_client=2;
                                sec=0;
                                web_client_attempts++;
                                // the identi.ca line is status=Url_encoded_string
                                strcat(statusstr,"status=");
                                // the text to send to identi.ca (append after status=):
                                //urlencode("Meals are ready",&(statusstr[7]));
                                urlencode("I like tuxgraphics eth boards, ",&(statusstr[7]));
                                // append a number:
                                itoa(web_client_attempts,&(statusstr[strlen(statusstr)]),10);
                                // The BLOGGACCOUNT Authorization code can be generated from 
                                // username and password of your identi.ca account 
                                // by using this encoder: http://tuxgraphics.org/~guido/javascript/base64-javascript.html
                                client_http_post(PSTR("/api/statuses/update.xml"),PSTR(WEBSERVER_VHOST),PSTR(BLOGGACCOUNT),statusstr,&browserresult_callback);
                        }
                        // count how often the switch was triggered at all:
                        if (contact_debounce==0 && bit_is_clear(PIND,PIND6)){
                                contact_onoff_cnt++;
                                contact_debounce=1;
                        }
                        // we send only a request if we are in the right state (do
                        // not flood with request):
                        if (start_web_client==0 && bit_is_clear(PIND,PIND6)){
                                resend=1; // resend once if it failed
                                start_web_client=1;
                        }
                        // Reset after a delay of 3 min to prevent email sending.
                        // We reset only if the contact on PD6 was released.
                        if (start_web_client<=3 && sec==180 && !bit_is_clear(PIND,PIND6)){
                                start_web_client=0;
                        }
                        // Resend the message if it failed:
                        if (start_web_client==2 && sec==7 && resend){
                                start_web_client=1;
                                resend--;
                        }
                        continue;
                }
                if(dat_p==0){ // plen!=0
                        // check for incomming messages not processed 
                        // as part of packetloop_icmp_tcp, e.g udp messages
                        udp_client_check_for_dns_answer(buf,plen);
                        continue;
                }
                        
                if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
                        // head, post and other methods:
                        //
                        // for possible status codes see:
                        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
                        dat_p=http200ok();
                        dat_p=fill_tcp_data_p(buf,dat_p,PSTR("<h1>200 OK</h1>"));
                        goto SENDTCP;
                }
                cmd=analyse_get_url((char *)&(buf[dat_p+4]));
                // for possible status codes see:
                // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
                if (cmd==-1){
                        dat_p=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>"));
                        goto SENDTCP;
                }
                if (cmd==1 && start_web_client==4){
                        // email was off, switch on
                        start_web_client=0;
                }
                if (cmd==0 ){
                        start_web_client=4; // email off
                }
                dat_p=http200ok();
                dat_p=print_webpage(buf);
                //
SENDTCP:
                www_server_reply(buf,dat_p); // send data

        }
        return (0);
}
int main(void){

        
        uint16_t dat_p;
        int8_t cmd;
        
        // Set the clock speed to "no pre-scaler" (8MHz with internal osc or 
        // full external speed)
        // set the clock prescaler. First write CLKPCE to enable setting 
        // of clock the next four instructions.
        // Note that the CKDIV8 Fuse determines the initial
        // value of the CKKPS bits.
        CLKPR=(1<<CLKPCE); // change enable
        CLKPR=0; // "no pre-scaler"
        _delay_loop_1(0); // 60us


        /*initialize enc28j60*/
        enc28j60Init(mymac);
        enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
        _delay_loop_1(0); // 60us
        
        /* Magjack leds configuration, see enc28j60 datasheet, page 11 */
        // LEDB=yellow LEDA=green
        //
        // 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
        // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10);
        enc28j60PhyWrite(PHLCON,0x476);
        
        DDRB|= (1<<DDB1); // LED, enable PB1, LED as output
        LEDOFF;

        DDRD&= ~(1<<DDD6); // enable PB6, as input
        PORTD|= (1<<PIND6); // internal pullup resistor on

        init_cnt2();
        sei();

        //init the web server ethernet/ip layer:
        init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT);
        // init the web client:
        client_set_gwip(gwip);  // e.g internal IP of dsl router
        client_set_wwwip(websrvip);
        //
        while(1){
                // handle ping and wait for a tcp packet
                dat_p=packetloop_icmp_tcp(buf,enc28j60PacketReceive(BUFFER_SIZE, buf));
                if(dat_p==0){
                        if (start_web_client==1){
                                LEDON;
                                start_web_client=2;
                                sec=0;
                                web_client_attempts++;
                                // the text to send in the body of the mail:
                                urlencode("The door is open",urlvarstr);
                                // The string "test+emailnotify" is the subject line
                                // of the email. A plus sign translates into a space character.
                                // The MMaccountID is gus123, edit and replace by your own.
                                client_browse_url(PSTR("/cgi-bin/mm?a=gus123&s=test+emailnotify&d="),urlvarstr,PSTR(WEBSERVER_VHOST),&browserresult_callback);
                        }
                        // count how often the switch was triggered at all:
                        if (contact_debounce==0 && bit_is_clear(PIND,PIND6)){
                                contact_onoff_cnt++;
                                contact_debounce=1;
                        }
                        // we send only an email if we are in the right state (do
                        // not flood with email):
                        if (start_web_client==0 && bit_is_clear(PIND,PIND6)){
                                resend=1; // resend once if it failed
                                start_web_client=1;
                        }
                        // Reset after a delay of 3 min to prevent email sending.
                        // We reset only if the contact on PD6 was released.
                        if (start_web_client<=3 && sec==180 && !bit_is_clear(PIND,PIND6)){
                                start_web_client=0;
                        }
                        // Resend the email if it failed:
                        if (start_web_client==2 && sec==7 && resend){
                                start_web_client=1;
                                resend--;
                        }
                        continue;
                }
                        
                if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
                        // head, post and other methods:
                        //
                        // for possible status codes see:
                        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
                        dat_p=http200ok();
                        dat_p=fill_tcp_data_p(buf,dat_p,PSTR("<h1>200 OK</h1>"));
                        goto SENDTCP;
                }
                cmd=analyse_get_url((char *)&(buf[dat_p+4]));
                // for possible status codes see:
                // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
                if (cmd==-1){
                        dat_p=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>"));
                        goto SENDTCP;
                }
                if (cmd==1 && start_web_client==4){
                        // email was off, switch on
                        start_web_client=0;
                }
                if (cmd==0 ){
                        start_web_client=4; // email off
                }
                dat_p=http200ok();
                dat_p=print_webpage(buf);
                //
SENDTCP:
                www_server_reply(buf,dat_p); // send data

        }
        return (0);
}
static void _eth_spi_handle_frame() {
  u16_t rx_stat;
  int plen = enc28j60PacketReceive(ETHSPI_MAX_PKT_SIZE, ethspi.rxbuf, &rx_stat);
  if (plen == 0) {
    DBG(D_ETH, D_DEBUG, "ethspi no frame, rx_stat:%04x\n", rx_stat);
    return;
  }
#ifdef ETH_STATS
  ethspi.rx_frames++;
  ethspi.rx_data += plen;
#endif

  DBG(D_ETH, D_DEBUG, "ethspi got frame, len %i, rx_stat:%04x\n", plen, rx_stat);
  //printbuf(ethspi.rxbuf, MIN(64, plen));
  // doing dhcp, do not allow anything else right now
  if (ethspi.dhcp.query && ethspi.dhcp.active) {
    int dhcp_res;
    dhcp_res = check_for_dhcp_answer(ethspi.rxbuf, plen);
    DBG(D_ETH, D_DEBUG, "ethspi DHCP:%i state:%i\n", dhcp_res, dhcp_state());
    if (dhcp_state() == DHCP_STATE_OK) {
      ethspi.dhcp.query = FALSE;
      DBG(D_ETH, D_DEBUG, "ethspi DHCP OK\n");
      DBG(D_ETH, D_INFO, "ethspi DHCP ip   %i.%i.%i.%i\n", ethspi.dhcp.ipaddr[0], ethspi.dhcp.ipaddr[1], ethspi.dhcp.ipaddr[2], ethspi.dhcp.ipaddr[3]);
      DBG(D_ETH, D_DEBUG, "ethspi DHCP gwip %i.%i.%i.%i\n", ethspi.dhcp.gwip[0], ethspi.dhcp.gwip[1], ethspi.dhcp.gwip[2], ethspi.dhcp.gwip[3]);
      DBG(D_ETH, D_DEBUG, "ethspi DHCP mask %i.%i.%i.%i\n", ethspi.dhcp.mask[0], ethspi.dhcp.mask[1], ethspi.dhcp.mask[2], ethspi.dhcp.mask[3]);
      DBG(D_ETH, D_DEBUG, "ethspi DHCP dhcp %i.%i.%i.%i\n", ethspi.dhcp.dhcp_server[0], ethspi.dhcp.dhcp_server[1], ethspi.dhcp.dhcp_server[2], ethspi.dhcp.dhcp_server[3]);
      DBG(D_ETH, D_DEBUG, "ethspi DHCP dns  %i.%i.%i.%i\n", ethspi.dhcp.dns_server[0], ethspi.dhcp.dns_server[1], ethspi.dhcp.dns_server[2], ethspi.dhcp.dns_server[3]);
      memcpy(ip_address, ethspi.dhcp.ipaddr, 4);
      set_ip(ethspi.dhcp.ipaddr);
      client_set_gwip(ethspi.dhcp.gwip);
#ifdef CONFIG_ETH_DHCP_SHOW
      print("eth ip address %i.%i.%i.%i\n", ethspi.dhcp.ipaddr[0], ethspi.dhcp.ipaddr[1], ethspi.dhcp.ipaddr[2], ethspi.dhcp.ipaddr[3]);
#endif
    }
    return;
  }

  // arp is broadcast if unknown but a host may also
  // verify the mac address by sending it to
  // a unicast address.
  if (eth_type_is_arp_and_my_ip(ethspi.rxbuf, plen)) {
    make_arp_answer_from_request(ethspi.rxbuf);
    return;
  }

  // check if ip frames (icmp or udp) are for us or broadcast:
  if (eth_type_is_ip_and_broadcast(ethspi.rxbuf, plen) == 0) {
    if (eth_type_is_ip_and_my_ip(ethspi.rxbuf, plen) == 0) {
      return;
    }
    if (ethspi.rxbuf[IP_PROTO_P]==IP_PROTO_ICMP_V &&
        ethspi.rxbuf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V){
      // a ping frame, let's send pong
      make_echo_reply_from_request(ethspi.rxbuf, plen);
      return;
    }
  }

#if 0
  // we listen on port 0xcafe
  if (ethspi.rxbuf[IP_PROTO_P] == IP_PROTO_UDP_V
      && ethspi.rxbuf[UDP_DST_PORT_H_P] == 0xca  && ethspi.rxbuf[UDP_DST_PORT_L_P] == 0xf) {
    int payloadlen = ethspi.rxbuf[UDP_LEN_L_P];//plen - 34 - UDP_HEADER_LEN;
    DBG(D_ETH, D_DEBUG, "ethspi UDP len:%i\n", payloadlen);
    //char *nisse = "hello wurlde";
    //make_udp_reply_from_request(ethbuf, nisse, strlen(nisse), 1200);
    DBG(D_ETH, D_DEBUG, "ethspi eth mac dst: %02x.%02x.%02x.%02x.%02x.%02x\n",
        ethspi.rxbuf[0], ethspi.rxbuf[1], ethspi.rxbuf[2], ethspi.rxbuf[3], ethspi.rxbuf[4], ethspi.rxbuf[5]); // ETH_DST_MAC
    DBG(D_ETH, D_DEBUG, "ethspi eth mac src: %02x.%02x.%02x.%02x.%02x.%02x\n",
        ethspi.rxbuf[6], ethspi.rxbuf[7], ethspi.rxbuf[8], ethspi.rxbuf[9], ethspi.rxbuf[10], ethspi.rxbuf[11]); // ETH_SRC_MAC
    DBG(D_ETH, D_DEBUG, "ethspi eth type:    %02x %02x\n",
        ethspi.rxbuf[12], ethspi.rxbuf[13]); // ETH_TYPE_H_P, ETH_TYPE_L_P
    DBG(D_ETH, D_DEBUG, "ethspi ip src:  %i.%i.%i.%i\n",
        ethspi.rxbuf[26], ethspi.rxbuf[27], ethspi.rxbuf[28], ethspi.rxbuf[29]); // IP_SRC_P
    DBG(D_ETH, D_DEBUG, "ethspi ip dst:  %i.%i.%i.%i\n",
        ethspi.rxbuf[30], ethspi.rxbuf[31], ethspi.rxbuf[32], ethspi.rxbuf[33]); // IP_DST_P
    DBG(D_ETH, D_DEBUG, "ethspi udp src port:  %i\n",
        (ethspi.rxbuf[34] << 8) | ethspi.rxbuf[35]); // UDP_SRC_PORT_H_P
    DBG(D_ETH, D_DEBUG, "ethspi udp dst port:  %i\n",
        (ethspi.rxbuf[36] << 8) | ethspi.rxbuf[37]); // UDP_DST_PORT_H_P
    DBG(D_ETH, D_DEBUG, "ethspi udp len:       %04x\n",
        (ethspi.rxbuf[38] << 8) | ethspi.rxbuf[39]); // UDP_LEN_H_P
    DBG(D_ETH, D_DEBUG, "ethspi udp checksum:  %04x\n",
        (ethspi.rxbuf[40] << 8) | ethspi.rxbuf[41]); // UDP_CHECKSUM_H_P
  }
  IF_DBG(D_ETH, D_DEBUG) {
    printbuf(&ethspi.rxbuf[0], plen);
  }