aboutsummaryrefslogblamecommitdiffstats
path: root/gg_map/gg_map.c
blob: dda280cea3dd1bbea60c6fd7ac16ca8f2a017d85 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                
                       
                   

                        
                     
 

               
                       
                             
                     
                            
 
                                               






                                               
 
 

                   

                         
                      









                                                           
           

                                                                    




                                                                           


                                                                     










                                                                    



                                      
                                


                                
                                                                  
                                 



                                                                      




           



























                                                     
                                                                        

                          
                 

                           
                                  


                                                  

                          

                                                                         




                                                                             




                                        
             
                                                                       
           




                                               


                                                     













                                           

                                                   



                                                          

                                                                              

                                                     
                                  



                                                
            

                                                                      
     
          

                                              


   
           
                                      
                          
                              

                     






                                                       

                                                  


                            
                        
                                             
                                                       

 












                                                                          

                                                        
 
                     

                                        




                                                         
 


                                                                        
            
 

                                        
                                                   

                                 
            
 
                     


                                                       
 
                                                   
            
 

                                     


                                                      
 
                                                                
            
   
 
           

 


































                                                                 






















                                                                  
           
                                                           
 





                               
                                         
                                                
             

                          
 

                                                  
                                                 
                                                                           
 

                                     
                                                                           
                                          

                       





                                                                           
































                                                                               



                                                                           
                            



                                                                     
                                                            

                                                               



                                                                          
                            




                                                                      
                            




                                                                       
                            




                                                                      
                            
 
                                                   

                                                                       
                        
                                     
                        

                   
 
                                                

              
                                                 
                                                             
                              
 




                                                                               
                                                 

            


             
                 
                

          
#include <err.h>

#include <Elementary.h>
#include <Egraph.h>

#include <libglouglou.h>
#include <libggnet.h>

int _debug = 0;

Evas_Object  *_mainwin;
Evas_Object  *_egraph = NULL;
struct ggnet *_ggnet;
struct event_base *_ev_base;

/* link between ecore loop and libevent loop */
static Eina_Bool
_cb_ecore_libevent(void *data) {
  if (event_base_got_exit(_ev_base))
    return EINA_FALSE;
  else
    event_base_loop(_ev_base, EVLOOP_NONBLOCK);
  return EINA_TRUE;
}

const char*
ip_to_str(u_int ip)
{
  unsigned char bytes[4];
  static char buf[16];

  bytes[0] = ip & 0xFF;
  bytes[1] = (ip >> 8) & 0xFF;
  bytes[2] = (ip >> 16) & 0xFF;
  bytes[3] = (ip >> 24) & 0xFF;	
  snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
           bytes[3], bytes[2], bytes[1], bytes[0]);        
  return buf;
}

static void
_cb_ggnet_addgroup(struct ggnet *net, struct ggnet_nodegroup *group,
                   struct ggnet_nodegroup *parent)
{
  Egraph_Vertice *vgroup;

  vgroup = egraph_group_add(_egraph, ip_to_str(group->addr.s_addr), group);
  ggnet_nodegroup_usrdata_set(group, vgroup);
  if (parent)
    egraph_group_vertice_attach(_egraph, vgroup,
                                ggnet_nodegroup_usrdata_get(parent));
}

static void
_cb_ggnet_delgroup(struct ggnet *net, struct ggnet_nodegroup *group)
{
  Egraph_Vertice *vgroup;

  vgroup = ggnet_nodegroup_usrdata_get(group);
  egraph_vertice_del(_egraph, vgroup);
}

static Egraph_Vertice *
_node_to_vertice(struct ggnet_node *n)
{
  Egraph_Vertice *v;
  struct ggnet_nodegroup *group;

  v = ggnet_node_usrdata_get(n);
  if (!v) {
    v = egraph_vertice_add(_egraph, ip_to_str(n->addr.s_addr), n);
    ggnet_node_usrdata_set(n, v);
    group = ggnet_node_group_get(n);
    if (group)
      egraph_group_vertice_attach(_egraph, v,
                                  ggnet_nodegroup_usrdata_get(group));
  }
  return v;
}

static void
_node_attach_parentgroup(struct ggnet_node *n)
{
  struct ggnet_nodegroup *g;
  Egraph_Vertice *vg, *vparentg;

  g = ggnet_node_group_get(n);
  if (!g || !g->parent)
    return;
  vg = ggnet_nodegroup_usrdata_get(g);
  vparentg = ggnet_nodegroup_usrdata_get(g->parent);
  egraph_group_vertice_attach(_egraph, vg, vparentg);
}

static void
_node_detach_parentgroup(struct ggnet_node *n)
{
  struct ggnet_nodegroup *g;
  Egraph_Vertice *vg, *vparentg;

  g = ggnet_node_group_get(n);
  if (!g || !g->parent)
    return;
  vg = ggnet_nodegroup_usrdata_get(g);
  vparentg = ggnet_nodegroup_usrdata_get(g->parent);
  egraph_group_vertice_detach(_egraph, vg, vparentg);
}

static void
_conn_add(u_int id, u_int src, u_int dst, u_int proto, u_int8_t pktsize)
{
  struct ggnet_conn *conn;
  Egraph_Edge *e;
  struct ggnet_node *a, *b;
  Egraph_Vertice *va, *vb;
  struct in_addr srcaddr, dstaddr;
  int size, response;

  GG_PKTDATA_SIZE_DECODE(pktsize, size, response);
  if (_debug)
    printf("_conn_add\n");
  if (response > 0) /* cannot have a new connection that is a response */
    return;

  srcaddr.s_addr = src;
  dstaddr.s_addr = dst;

  conn = ggnet_conn_add(_ggnet, &srcaddr, -1, &dstaddr, -1, proto, size, id);
  a = ggnet_conn_src_get(conn);
  b = ggnet_conn_dst_get(conn);
  va = _node_to_vertice(a);
  vb = _node_to_vertice(b);
  e = egraph_edge_find(_egraph, va, vb);
  if (_debug)
    printf("_conn_add: a %d b %d e %x id %d\n", va->id, vb->id, e, id);
  if (!e) {
    if (a->group && a->group->conn_count == 1)
      _node_detach_parentgroup(a);
    if (b->group && b->group->conn_count == 1)
      _node_detach_parentgroup(b);
    e = egraph_edge_add(_egraph, va, vb, conn);
    if (_debug)
      printf("_conn_add: egraph edge added %x\n", e);
  }
  ggnet_conn_usrdata_set(conn, e);
}

static void
_conn_del(int id) {
  struct ggnet_conn *conn, *otherconn;
  struct ggnet_node *a, *b;
  Egraph_Edge *e;

  conn = ggnet_conn_find_by_id(_ggnet, id);
  if (conn) {
    a = ggnet_conn_src_get(conn);
    b = ggnet_conn_dst_get(conn);
    e = ggnet_conn_usrdata_get(conn);
    if (_debug)
      printf("_conn_del: conn id %d\n", id); // XXX
    ggnet_conn_del(_ggnet, conn);
    /* is there other connections between these peers ? */
    otherconn = ggnet_conn_find_by_node(_ggnet, a, b);
    if (!otherconn) {
      // XXX lets keep the edges, igraph layouting behaves badly when you have
      // a vertice without edge ...
      if (_debug)
        printf("_conn_del: edge del %x\n", e); // XXX
      egraph_edge_del(_egraph, e);
      if (a->group && a->group->conn_count == 0)
        _node_attach_parentgroup(a);
      if (b->group && b->group->conn_count == 0)
        _node_attach_parentgroup(b);
    } else {
      if (_debug)
        printf("_conn_del: not last one, edge %x *not* deleted\n", e);
    }
  } else {
    if (_debug)
      printf("_conn_del: does not exist !\n");
  }
}

static void
_conn_data(int id, u_int8_t pktsize) {
  struct ggnet_conn *conn;
  Egraph_Vertice *a, *b, *tmp;
  int size, response;
  u_int32_t color;

  conn = ggnet_conn_find_by_id(_ggnet, id);
  if (!conn)
    return;

  a = ggnet_node_usrdata_get(ggnet_conn_src_get(conn));
  b = ggnet_node_usrdata_get(ggnet_conn_dst_get(conn));

  GG_PKTDATA_SIZE_DECODE(pktsize, size, response);
  if (response) {
    tmp = a; a = b; b = tmp;
  }
  size = sqrt(size) / 2;
  color = ((id+1) * 0x98765400) % 0xFFFFFF00;
  egraph_vertice_send_blob(_egraph, a, b, size, color);
}

static void
_conn_name(u_int32_t addr, u_int8_t pktsize, u_char *fqdn) {
  struct ggnet_node *n;
  struct in_addr ip;

  ip.s_addr = addr;
  n = ggnet_node_find(_ggnet, &ip);
  if (!n)
    return;

  egraph_vertice_rename(_egraph, ggnet_node_usrdata_get(n), (char *)fqdn);
}

int
_cb_packet(struct gg_client *cli, struct gg_packet *pkt)
{
  switch(pkt->type) {
    case PACKET_NEWCONN:
      printf("  type PACKET_NEWCONN\n");
      printf("  newconn_id %d\n", pkt->newconn_id);
      printf("  newconn_src %4x\n", pkt->newconn_src);
      printf("  newconn_dst %4x\n", pkt->newconn_dst);
      printf("  newconn_proto %d\n", pkt->newconn_proto);
      printf("  newconn_size %d\n", pkt->newconn_size);

      _conn_del(pkt->newconn_id); /* in case we missed a previous del */
      _conn_add(pkt->newconn_id, pkt->newconn_src, pkt->newconn_dst,
                pkt->newconn_proto, pkt->newconn_size);
      break;

    case PACKET_DELCONN:
      printf("  type PACKET_DELCONN\n");
      printf("  delconn_id %d\n", pkt->delconn_id);
      
      _conn_del(pkt->delconn_id);
      break;

    case PACKET_DATA:
      //printf("  type PACKET_DATA\n");
      //printf("  data_connid %d\n", pkt->data_connid);
      //printf("  data_size %d\n", pkt->data_size);

      _conn_data(pkt->data_connid, pkt->data_size);
      break;

    case PACKET_NAME:
      printf("  type PACKET_NAME\n");
      printf("  name_addr %4x\n", pkt->name_addr);
      printf("  name_len %d\n", pkt->name_len);
      printf("  name_name_fqdn %s\n", pkt->name_fqdn);

      _conn_name(pkt->name_addr, pkt->name_len, pkt->name_fqdn);
      break;
  }

  return 0;
}

/* static void
_cb_del_edges(void *data, Evas_Object *obj, void *event_info)
{
  if (!_egraph)
    return;

  // XXX ggnet_clear(_ggnet);
  egraph_clear(_egraph);
} */

static void
_cb_show_nodes(void *data, Evas_Object *obj, void *event_info)
{
  egraph_display_vertices_set(_egraph, elm_check_state_get(obj));
}

static void
_cb_show_labels(void *data, Evas_Object *obj, void *event_info)
{
  if (!_egraph)
    return;

  egraph_display_names_set(_egraph, elm_check_state_get(obj));
}

static void
_cb_show_edges(void *data, Evas_Object *obj, void *event_info)
{
  if (!_egraph)
    return;

  egraph_display_edges_set(_egraph, elm_check_state_get(obj));
}

static void
_cb_layout_changed(void *data, Evas_Object *obj, void *event_info)
{
  Elm_Object_Item *it;
  char *selected;
  int layout;

  if (!_egraph)
    return;

  it = event_info;
  selected = elm_object_item_text_get(it);
  layout = EGRAPH_LAYOUT_DEFAULT;
  if (!strcmp(selected, "Kamada K."))
    layout = EGRAPH_LAYOUT_KAMADAKAWAI;
  else if (!strcmp(selected, "GraphOpt"))
    layout = EGRAPH_LAYOUT_GRAPHOPT;
  else if (!strcmp(selected, "Fruchterman R."))
    layout = EGRAPH_LAYOUT_FRUCHTERMANREINGOLD;

  egraph_layout_set(_egraph, layout);
}


static void
_cb_on_done(void *data, Evas_Object *obj, void *event_info)
{
  elm_exit();
}

EAPI_MAIN int
elm_main(int argc, char **argv)
{
  Evas_Object *win, *bg, *egraph, *panes;
  Evas_Object *bx, *bx2, *ck, *sc, *seg_it, *lb;
  Evas *evas;
  struct gg_client *ggcli;
  int retval = -1;

  win = elm_win_add(NULL, "panes", ELM_WIN_BASIC);
  evas = evas_object_evas_get(win);
  elm_win_title_set(win, "Glouglou Network Map");
  evas_object_smart_callback_add(win, "delete,request", _cb_on_done, NULL);

  bg = elm_bg_add(win);
  elm_win_resize_object_add(win, bg);
  evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  evas_object_color_set(bg, 0, 0, 0, 255);
  evas_object_show(bg);

  bx = elm_box_add(win);
  elm_box_horizontal_set(bx, EINA_TRUE);
  evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  elm_win_resize_object_add(win, bx);
  evas_object_show(bx);

  panes = elm_panes_add(win);
  evas_object_size_hint_weight_set(panes, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  evas_object_size_hint_align_set(panes, EVAS_HINT_FILL, EVAS_HINT_FILL);
  elm_panes_content_right_size_set(panes, 0.0);
  elm_box_pack_end(bx, panes);
  evas_object_show(panes);

  egraph = egraph_new(evas, 1);
  egraph_layout_set(egraph, EGRAPH_LAYOUT_KAMADAKAWAI);
  if (!egraph)
    goto quit;
  evas_object_size_hint_weight_set(egraph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  evas_object_size_hint_align_set(egraph, EVAS_HINT_FILL, EVAS_HINT_FILL);
  evas_object_show(egraph);
  elm_object_part_content_set(panes, "left", egraph);

  bx2 = elm_box_add(win);
  //elm_box_horizontal_set(bx, EINA_FALSE);
  evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
  evas_object_color_set(bx2, 255, 255, 255, 100); // XXX broken
  evas_object_show(bx2);

  lb = elm_label_add(win);
  elm_object_style_set(lb, "marker");
  evas_object_color_set(lb, 255, 255, 255, 255);
  elm_object_text_set(lb,
          "Glouglou Network Mapper<br/>"
          "<br/>"
          "Enjoy !<br/>");
  evas_object_show(lb);
  elm_box_pack_end(bx2, lb);

  lb = elm_label_add(win);
  elm_object_text_set(lb, "<b>Layout</b>");
  evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, EVAS_HINT_FILL);
  elm_box_pack_end(bx2, lb);
  sc = elm_segment_control_add(win);
  //evas_object_size_hint_weight_set(sc, em->weight.w, em->weight.h);
  //evas_object_size_hint_align_set(sc, em->align.x, em->align.y);
  seg_it = elm_segment_control_item_add(sc, NULL, "GraphOpt");
  elm_segment_control_item_selected_set(seg_it, EINA_FALSE);
  seg_it = elm_segment_control_item_add(sc, NULL, "Kamada K.");
  elm_segment_control_item_selected_set(seg_it, EINA_TRUE);
  seg_it = elm_segment_control_item_add(sc, NULL, "Fruchterman R.");
  elm_segment_control_item_selected_set(seg_it, EINA_FALSE);
  evas_object_smart_callback_add(sc, "changed", _cb_layout_changed, NULL);
  evas_object_show(sc);
  elm_box_pack_end(bx2, sc);
  ck = elm_check_add(win);
  elm_object_text_set(ck, "Show Node");
  elm_check_state_set(ck, EINA_TRUE);
  evas_object_show(ck);
  evas_object_smart_callback_add(ck, "changed", _cb_show_nodes, NULL);
  elm_box_pack_end(bx2, ck);
  ck = elm_check_add(win);
  elm_object_text_set(ck, "Show Label");
  elm_check_state_set(ck, EINA_TRUE);
  evas_object_show(ck);
  evas_object_smart_callback_add(ck, "changed", _cb_show_labels, NULL);
  elm_box_pack_end(bx2, ck);
  ck = elm_check_add(win);
  elm_object_text_set(ck, "Show Edges");
  elm_check_state_set(ck, EINA_TRUE);
  evas_object_show(ck);
  evas_object_smart_callback_add(ck, "changed", _cb_show_edges, NULL);
  elm_box_pack_end(bx2, ck);

  elm_object_part_content_set(panes, "right", bx2);

  evas_object_resize(win, 150, 150); // XXX workaround elm sizing issue
  evas_object_show(win);
  evas_object_resize(win, 1300, 715);
  evas_object_show(win);
  _egraph = egraph;
  _mainwin = win;

  _ggnet = ggnet_new(GGNET_MANAGE_CONNID_FALSE);
  if (!_ggnet)
    goto quit;
  ggnet_set_grouping(_ggnet, GGNET_GROUPING_TRUE,
                     _cb_ggnet_addgroup, _cb_ggnet_delgroup);
  _ev_base = event_base_new();

  ggcli = gg_client_connect(_ev_base, "127.0.0.1", GLOUGLOU_ANALY_DEFAULT_PORT,
                            NULL, _cb_packet, NULL);
  if (!ggcli)
    goto quit;

  ecore_timer_add(0.1, _cb_ecore_libevent, NULL);

  elm_run();
  retval = 0;

quit:
  elm_shutdown();
  return retval;
}
ELM_MAIN()