Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie by
Diff: libs/Network/uip/Network.cpp
- Revision:
- 3:f151d08d335c
- Parent:
- 2:1df0b61d3b5a
--- a/libs/Network/uip/Network.cpp Fri Feb 28 18:52:52 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,428 +0,0 @@ -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#pragma GCC diagnostic ignored "-Wcast-qual" -#pragma GCC diagnostic ignored "-Wcast-align" - -#include "CommandQueue.h" - -#include "Kernel.h" - -#include "Network.h" -#include "PublicDataRequest.h" -#include "PlayerPublicAccess.h" -#include "net_util.h" -#include "uip_arp.h" -#include "clock-arch.h" - -#include "uip.h" -#include "telnetd.h" -#include "webserver.h" -#include "dhcpc.h" -#include "sftpd.h" - - -#include <mri.h> - -#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) - -extern "C" void uip_log(char *m) -{ - printf("uIP log message: %s\n", m); -} - -static bool webserver_enabled, telnet_enabled, use_dhcp; -static Network *theNetwork; -static Sftpd *sftpd; -static CommandQueue *command_q= CommandQueue::getInstance(); - -Network* Network::instance; -Network::Network() -{ - ethernet = new LPC17XX_Ethernet(); - tickcnt= 0; - theNetwork= this; - sftpd= NULL; - instance= this; -} - -Network::~Network() -{ - delete ethernet; -} - -static uint32_t getSerialNumberHash() -{ -#define IAP_LOCATION 0x1FFF1FF1 - uint32_t command[1]; - uint32_t result[5]; - typedef void (*IAP)(uint32_t *, uint32_t *); - IAP iap = (IAP) IAP_LOCATION; - - __disable_irq(); - - command[0] = 58; - iap(command, result); - __enable_irq(); - return crc32((uint8_t *)&result[1], 4 * 4); -} - -static bool parse_ip_str(const string &s, uint8_t *a, int len, char sep = '.') -{ - int p = 0; - const char *n; - for (int i = 0; i < len; i++) { - if (i < len - 1) { - size_t o = s.find(sep, p); - if (o == string::npos) return false; - n = s.substr(p, o - p).c_str(); - p = o + 1; - } else { - n = s.substr(p).c_str(); - } - a[i] = atoi(n); - } - return true; -} - -void Network::on_module_loaded() -{ - if ( !THEKERNEL->config->value( network_checksum, network_enable_checksum )->by_default(false)->as_bool() ) { - // as not needed free up resource - delete this; - return; - } - - webserver_enabled = THEKERNEL->config->value( network_checksum, network_webserver_checksum, network_enable_checksum )->by_default(false)->as_bool(); - telnet_enabled = THEKERNEL->config->value( network_checksum, network_telnet_checksum, network_enable_checksum )->by_default(false)->as_bool(); - - string mac = THEKERNEL->config->value( network_checksum, network_mac_override_checksum )->by_default("")->as_string(); - if (mac.size() == 17 ) { // parse mac address - if (!parse_ip_str(mac, mac_address, 6, ':')) { - printf("Invalid MAC address: %s\n", mac.c_str()); - printf("Network not started due to errors in config"); - return; - } - - } else { // autogenerate - uint32_t h = getSerialNumberHash(); - mac_address[0] = 0x00; // OUI - mac_address[1] = 0x1F; // OUI - mac_address[2] = 0x11; // OUI - mac_address[3] = 0x02; // Openmoko allocation for smoothie board - mac_address[4] = 0x04; // 04-14 03 bits -> chip id, 1 bits -> hashed serial - mac_address[5] = h & 0xFF; // 00-FF 8bits -> hashed serial - } - - ethernet->set_mac(mac_address); - - // get IP address, mask and gateway address here.... - bool bad = false; - string s = THEKERNEL->config->value( network_checksum, network_ip_address_checksum )->by_default("auto")->as_string(); - if (s == "auto") { - use_dhcp = true; - - } else { - use_dhcp = false; - if (!parse_ip_str(s, ipaddr, 4)) { - printf("Invalid IP address: %s\n", s.c_str()); - bad = true; - } - s = THEKERNEL->config->value( network_checksum, network_ip_mask_checksum )->by_default("255.255.255.0")->as_string(); - if (!parse_ip_str(s, ipmask, 4)) { - printf("Invalid IP Mask: %s\n", s.c_str()); - bad = true; - } - s = THEKERNEL->config->value( network_checksum, network_ip_gateway_checksum )->by_default("192.168.3.1")->as_string(); - if (!parse_ip_str(s, ipgw, 4)) { - printf("Invalid IP gateway: %s\n", s.c_str()); - bad = true; - } - - if (bad) { - printf("Network not started due to errors in config"); - return; - } - } - - THEKERNEL->add_module( ethernet ); - THEKERNEL->slow_ticker->attach( 100, this, &Network::tick ); - - // Register for events - this->register_for_event(ON_IDLE); - this->register_for_event(ON_MAIN_LOOP); - this->register_for_event(ON_GET_PUBLIC_DATA); - - this->init(); -} - -void Network::on_get_public_data(void* argument) { - PublicDataRequest* pdr = static_cast<PublicDataRequest*>(argument); - - if(!pdr->starts_with(network_checksum)) return; - - if(pdr->second_element_is(get_ip_checksum)) { - pdr->set_data_ptr(this->ipaddr); - pdr->set_taken(); - - }else if(pdr->second_element_is(get_ipconfig_checksum)) { - // NOTE caller must free the returned string when done - char buf[200]; - int n1= snprintf(buf, sizeof(buf), "IP Addr: %d.%d.%d.%d\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); - int n2= snprintf(&buf[n1], sizeof(buf)-n1, "IP GW: %d.%d.%d.%d\n", ipgw[0], ipgw[1], ipgw[2], ipgw[3]); - int n3= snprintf(&buf[n1+n2], sizeof(buf)-n1-n2, "IP mask: %d.%d.%d.%d\n", ipmask[0], ipmask[1], ipmask[2], ipmask[3]); - int n4= snprintf(&buf[n1+n2+n3], sizeof(buf)-n1-n2-n3, "MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n", - mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]); - char *str = (char *)malloc(n1+n2+n3+n4+1); - memcpy(str, buf, n1+n2+n3+n4); - str[n1+n2+n3+n4]= '\0'; - pdr->set_data_ptr(str); - pdr->set_taken(); - } -} - -uint32_t Network::tick(uint32_t dummy) -{ - do_tick(); - tickcnt++; - return 0; -} - -void Network::on_idle(void *argument) -{ - if (!ethernet->isUp()) return; - - int len; - if (ethernet->_receive_frame(uip_buf, &len)) { - uip_len = len; - this->handlePacket(); - - } else { - - if (timer_expired(&periodic_timer)) { /* no packet but periodic_timer time out (0.1s)*/ - timer_reset(&periodic_timer); - - for (int i = 0; i < UIP_CONNS; i++) { - uip_periodic(i); - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ - if (uip_len > 0) { - uip_arp_out(); - tapdev_send(uip_buf, uip_len); - } - } - -#if UIP_CONF_UDP - for (int i = 0; i < UIP_UDP_CONNS; i++) { - uip_udp_periodic(i); - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ - if (uip_len > 0) { - uip_arp_out(); - tapdev_send(uip_buf, uip_len); - } - } -#endif - } -/* - This didn't work actually made it worse,it should have worked though - else{ - // TODO if the command queue is below a certain amount we should poll any stopped connections - if(command_q->size() < 4) { - for (struct uip_conn *connr = &uip_conns[0]; connr <= &uip_conns[UIP_CONNS - 1]; ++connr) { - if(uip_stopped(connr)){ - // Force a poll of this - printf("Force poll of connection\n"); - uip_poll_conn(connr); - } - } - } - } -*/ - /* Call the ARP timer function every 10 seconds. */ - if (timer_expired(&arp_timer)) { - timer_reset(&arp_timer); - uip_arp_timer(); - } - } -} - -static void setup_servers() -{ - if (webserver_enabled) { - // Initialize the HTTP server, listen to port 80. - httpd_init(); - printf("Webserver initialized\n"); - } - - if (telnet_enabled) { - // Initialize the telnet server - Telnetd::init(); - printf("Telnetd initialized\n"); - } - - // sftpd service, which is lazily created on reciept of first packet - uip_listen(HTONS(115)); -} - -extern "C" void dhcpc_configured(const struct dhcpc_state *s) -{ - printf("Got IP address %d.%d.%d.%d\n", - uip_ipaddr1(&s->ipaddr), uip_ipaddr2(&s->ipaddr), - uip_ipaddr3(&s->ipaddr), uip_ipaddr4(&s->ipaddr)); - printf("Got netmask %d.%d.%d.%d\n", - uip_ipaddr1(&s->netmask), uip_ipaddr2(&s->netmask), - uip_ipaddr3(&s->netmask), uip_ipaddr4(&s->netmask)); - printf("Got DNS server %d.%d.%d.%d\n", - uip_ipaddr1(&s->dnsaddr), uip_ipaddr2(&s->dnsaddr), - uip_ipaddr3(&s->dnsaddr), uip_ipaddr4(&s->dnsaddr)); - printf("Got default router %d.%d.%d.%d\n", - uip_ipaddr1(&s->default_router), uip_ipaddr2(&s->default_router), - uip_ipaddr3(&s->default_router), uip_ipaddr4(&s->default_router)); - printf("Lease expires in %ld seconds\n", ntohl(s->lease_time)); - - theNetwork->dhcpc_configured(s->ipaddr, s->netmask, s->default_router); -} - -void Network::dhcpc_configured(uint32_t ipaddr, uint32_t ipmask, uint32_t ipgw) -{ - memcpy(this->ipaddr, &ipaddr, 4); - memcpy(this->ipmask, &ipmask, 4); - memcpy(this->ipgw, &ipgw, 4); - - uip_sethostaddr((u16_t*)this->ipaddr); - uip_setnetmask((u16_t*)this->ipmask); - uip_setdraddr((u16_t*)this->ipgw); - - setup_servers(); -} - -void Network::init(void) -{ - // two timers for tcp/ip - timer_set(&periodic_timer, CLOCK_SECOND / 2); /* 0.5s */ - timer_set(&arp_timer, CLOCK_SECOND * 10); /* 10s */ - - // Initialize the uIP TCP/IP stack. - uip_init(); - - uip_setethaddr(mac_address); - - if (!use_dhcp) { // manual setup of ip - uip_ipaddr_t tip; /* local IP address */ - uip_ipaddr(tip, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); - uip_sethostaddr(tip); /* host IP address */ - printf("IP Addr: %d.%d.%d.%d\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); - - uip_ipaddr(tip, ipgw[0], ipgw[1], ipgw[2], ipgw[3]); - uip_setdraddr(tip); /* router IP address */ - printf("IP GW: %d.%d.%d.%d\n", ipgw[0], ipgw[1], ipgw[2], ipgw[3]); - - uip_ipaddr(tip, ipmask[0], ipmask[1], ipmask[2], ipmask[3]); - uip_setnetmask(tip); /* mask */ - printf("IP mask: %d.%d.%d.%d\n", ipmask[0], ipmask[1], ipmask[2], ipmask[3]); - setup_servers(); - - }else{ - #if UIP_CONF_UDP - dhcpc_init(mac_address, sizeof(mac_address)); - dhcpc_request(); - printf("Getting IP address....\n"); - #endif - } -} - -void Network::on_main_loop(void *argument) -{ - // issue commands here if any available - while(command_q->pop()) { - // keep feeding them until empty - } -} - -// select between webserver and telnetd server -extern "C" void app_select_appcall(void) -{ - switch (uip_conn->lport) { - case HTONS(80): - if (webserver_enabled) httpd_appcall(); - break; - - case HTONS(23): - if (telnet_enabled) Telnetd::appcall(); - break; - - case HTONS(115): - if(sftpd == NULL) { - sftpd= new Sftpd(); - sftpd->init(); - printf("Created sftpd service\n"); - } - sftpd->appcall(); - break; - - default: - printf("unknown app for port: %d\n", uip_conn->lport); - - } -} - -void Network::tapdev_send(void *pPacket, unsigned int size) -{ - memcpy(ethernet->request_packet_buffer(), pPacket, size); - ethernet->write_packet((uint8_t *) pPacket, size); -} - -// define this to split full frames into two to illicit an ack from the endpoint -#define SPLIT_OUTPUT - -#ifdef SPLIT_OUTPUT -extern "C" void uip_split_output(void); -extern "C" void tcpip_output() -{ - theNetwork->tapdev_send(uip_buf, uip_len); -} -void network_device_send() -{ - uip_split_output(); - //tcpip_output(); -} -#else -void network_device_send() -{ - tapdev_send(uip_buf, uip_len); -} -#endif - -void Network::handlePacket(void) -{ - if (uip_len > 0) { /* received packet */ - //printf("handlePacket: %d\n", uip_len); - - if (BUF->type == htons(UIP_ETHTYPE_IP)) { /* IP packet */ - uip_arp_ipin(); - uip_input(); - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ - - if (uip_len > 0) { - uip_arp_out(); - network_device_send(); - } - - } else if (BUF->type == htons(UIP_ETHTYPE_ARP)) { /*ARP packet */ - uip_arp_arpin(); - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ - if (uip_len > 0) { - tapdev_send(uip_buf, uip_len); /* ARP ack*/ - } - - } else { - printf("Unknown ethernet packet type %04X\n", htons(BUF->type)); - uip_len = 0; - } - } -}