text: /*
   * Copyright (c) 2017, RISE SICS
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. Neither the name of the Institute nor the names of its contributors
   *    may be used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
   * This file is part of the Contiki operating system.
   *
   */
  
  #include "contiki.h"
  #include "net/routing/routing.h"
  #include "net/ipv6/uip-ds6-nbr.h"
  #include "net/ipv6/uip-ds6-route.h"
  #include "net/ipv6/uip-sr.h"
  
  #include <stdio.h>
  #include <string.h>
  #include <sys/stat.h>
  #include <sys/types.h>
  #include <fcntl.h>
  #include <unistd.h>
  #include <stdlib.h>
  
  #define FIFO_FILE_DOWN "DOWNFIFO"
  #define DOWNWARD_PORT	5678
  static char buff[100];
  static struct simple_udp_connection downward_conn;
  
  /*---------------------------------------------------------------------------*/
  static const char *TOP = "<html>\n  <head>\n    <title>Contiki-NG</title>\n  </head>\n<body>\n";
  static const char *BOTTOM = "\n</body>\n</html>\n";
  static char buf[256];
  static int blen;
  #define ADD(...) do {                                                   \
      blen += snprintf(&buf[blen], sizeof(buf) - blen, __VA_ARGS__);      \
    } while(0)
  #define SEND(s) do { \
    SEND_STRING(s, buf); \
    blen = 0; \
  } while(0);
  
  /* Use simple webserver with only one page for minimum footprint.
   * Multiple connections can result in interleaved tcp segments since
   * a single static buffer is used for all segments.
   */
  #include "httpd-simple.h"
  
  /*---------------------------------------------------------------------------*/
  static void
  ipaddr_add(const uip_ipaddr_t *addr)
  {
    uint16_t a;
    int i, f;
    for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
      a = (addr->u8[i] << 8) + addr->u8[i + 1];
      if(a == 0 && f >= 0) {
        if(f++ == 0) {
          ADD("::");
        }
      } else {
        if(f > 0) {
          f = -1;
        } else if(i > 0) {
          ADD(":");
        }
        ADD("%x", a);
      }
    }
  }
  
  /*---------------------------------------------------------------------------*/
  static int fd;
  // const char wait[4] = "WAIT";
  static uip_ipaddr_t new_parent;
  
  /*---------------------------------------------------------------------------*/
  
  static
  PT_THREAD(generate_routes(struct httpd_state *s))
  {
    static uip_ds6_nbr_t *nbr;
  
    PSOCK_BEGIN(&s->sout);
    SEND_STRING(&s->sout, TOP);
  
  
    // read_pipe();
    ADD("  Neighbors\n  <ul>\n");
    SEND(&s->sout);
    for(nbr = uip_ds6_nbr_head();
        nbr != NULL;
        nbr = uip_ds6_nbr_next(nbr)) {
      ADD("    <li>");
      ipaddr_add(&nbr->ipaddr);
      ADD("</li>\n");
      SEND(&s->sout);
    }
    ADD("  </ul>\n");
    SEND(&s->sout);
  
  #if (UIP_MAX_ROUTES != 0)
    {
      static uip_ds6_route_t *r;
      ADD("  Routes\n  <ul>\n");
      SEND(&s->sout);
      for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) {
        ADD("    <li>");
        ipaddr_add(&r->ipaddr);
        ADD("/%u (via ", r->length);
        ipaddr_add(uip_ds6_route_nexthop(r));
        ADD(") %lus", (unsigned long)r->state.lifetime);
        ADD("</li>\n");
        SEND(&s->sout);
      }
      ADD("  </ul>\n");
      SEND(&s->sout);
    }
  #endif /* UIP_MAX_ROUTES != 0 */
  
  #if (UIP_SR_LINK_NUM != 0)
    if(uip_sr_num_nodes() > 0) {
      static uip_sr_node_t *link;
      ADD("  Routing links\n  <ul>\n");
      SEND(&s->sout);
      for(link = uip_sr_node_head(); link != NULL; link = uip_sr_node_next(link)) {
        if(link->parent != NULL) {
          uip_ipaddr_t child_ipaddr;
          uip_ipaddr_t parent_ipaddr;
  
          NETSTACK_ROUTING.get_sr_node_ipaddr(&child_ipaddr, link);
          NETSTACK_ROUTING.get_sr_node_ipaddr(&parent_ipaddr, link->parent);
  
          ADD("    <li>");
          ipaddr_add(&child_ipaddr);
  
          ADD(" (parent: ");
          ipaddr_add(&parent_ipaddr);
          ADD(") %us", (unsigned int)link->lifetime);
  
          ADD("</li>\n");
          SEND(&s->sout);
        }
      }
      ADD("  </ul>");
      SEND(&s->sout);
    }
  #endif /* UIP_SR_LINK_NUM != 0 */
  
    SEND_STRING(&s->sout, BOTTOM);
  
    PSOCK_END(&s->sout);
  }
  /*---------------------------------------------------------------------------*/
  PROCESS(webserver_nogui_process, "Web server");
  PROCESS_THREAD(webserver_nogui_process, ev, data)
  {
    PROCESS_BEGIN();
  
    httpd_init();
    mkfifo(FIFO_FILE_DOWN, 0666);
    simple_udp_register(&downward_conn, DOWNWARD_PORT, NULL,
            DOWNWARD_PORT, NULL);                        
  
    while(1) {
      PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event);
      httpd_appcall(data);
    }
  
    PROCESS_END();
  }
  /*---------------------------------------------------------------------------*/
  httpd_simple_script_t
  httpd_simple_get_script(const char *name)
  {
    return generate_routes;
  }
  /*---------------------------------------------------------------------------*/
  