#!/usr/bin/perl -w

#--------------------------------------------------------------------
# Fichero:  internet.pl
# Objetivo: Controlar la conexión a internet
# Autor:    Pedro Reina <pedro@pedroreina.net>
# Licencia: Dominio público
# Fecha:    S.16.7.2005
#--------------------------------------------------------------------

#--------------------------------------------------------------------
# Este programa propone una manera de conectar y desconectar a
# Internet pensado para que el usuario final lo pueda utilizar
# sin saber los detalles del método de conexión. Los responsables
# de la administración de la máquina saben los detalles de la conexión
# y prepara las órdenes correspondientes, que anota como variables
# en el programa. Se ofrecen además en el interfaz del programa las
# entradas que permiten conocer la IP de la máquina y el número
# de paquetes que entran y salen por el interfaz de red
#
# Cada vez que se produzca la conexión habrá que anotar en /var/run/ip
# la dirección IP obtenida, ya que este programa comprueba que exista
# ese archivo
#--------------------------------------------------------------------

#---------------------------------
# Declaración de módulos
#---------------------------------

use strict;              # Comprobaciones estrictas
use Gtk;                 # Interfaz gráfico GTK

#---------------------------------
# Declaración de variables Perl
# Hay que adaptarlas en cada caso
#---------------------------------

# Interfaz que hay que controlar
my $Interfaz = "";

# Orden para leer la configuración
my $OrdenConf = "";

# Orden para conectar a Internet
my $OrdenConectar = "";

# Orden para desconectar de Internet
my $OrdenDesconectar = "";

#---------------------------------
# Ejemplos de configuración
# para distintos tipos de conexión
#---------------------------------

# Conexión con PPPoE
# $Interfaz = "ppp0";
# $OrdenConf = "/sbin/ifconfig";
# $OrdenConectar = "sudo /usr/bin/pon";
# $OrdenDesconectar = "sudo /usr/bin/poff -a";

# Conexión con DHCP
# $Interfaz = "eth0";
# $OrdenConf = "/sbin/ifconfig";
# $OrdenConectar = "sudo /sbin/ifup eth0";
# Orden para desconectar de Internet
# $OrdenDesconectar = "sudo /sbin/ifdown eth0";

# Conexión con ISDN (RDSI)
# $Interfaz = "ippp0";
# $OrdenConf = "/sbin/ifconfig";
# $OrdenConectar = "sudo isdnctrl dial ippp0";
# $OrdenDesconectar = "sudo isdnctrl hangup ippp0";

# Conexión por módem usando wvdial
# $Interfaz = "ppp0";
# $OrdenConf = "/sbin/ifconfig";
# $OrdenConectar = "sudo wvdial&";
# $OrdenDesconectar = "sudo killall -s KILL wvdial; sudo killall pppd";

#---------------------------------
# Declaración de variables GTK
# Normalmente no hay que tocarlas
#---------------------------------

my $Ventana;                   # Ventana de la aplicación
my $Tabla;                     # Un contenedor para los controles
my $EtiquetaInterfaz;          # Para indicar el interfaz
my $BotonConectar;             # El botón para conectar el interfaz
my $BotonDesconectar;          # El botón para desconectar el interfaz
my $EtiquetaEstado;            # Para indicar el estado del interfaz
my $EtiquetaTextoEstado;       # Para decir el estado del interfaz
my $EtiquetaDireccionIP;       # Para indicar el texto de la dirección IP
my $EtiquetaNumeroDireccionIP; # Para indicar la dirección IP
my $EtiquetaEntrada;           # Para indicar el texto de los paquetes que entran
my $EtiquetaPaquetesEntrada;   # Para indicar los paquetes que entran
my $EtiquetaSalida;            # Para indicar el texto de los paquetes que salen
my $EtiquetaPaquetesSalida;    # Para indicar los paquetes que salen
my $BotonCerrar;               # El botón para cerrar la aplicación
my $Temporizador = 0;          # Un temporizador para monitorizar la interfaz

#---------------------------------
# Programa principal
#---------------------------------

# Arrancamos el motor GTK;
init Gtk;

# Creamos la ventana principal
$Ventana = new Gtk::Window ("toplevel");

# Le ponemos un título
$Ventana->set_title ("Internet");

# Le ponemos un poquito de borde
$Ventana->border_width (10);

# Creamos la tabla para poner los controles
$Tabla = new Gtk::Table (7, 2, 1);

# Separamos un poquito las celdas
$Tabla->set_row_spacings (4);
$Tabla->set_col_spacings (4);

# Definimos las etiquetas
$EtiquetaInterfaz = new Gtk::Label ("Conexión a Internet");
$EtiquetaDireccionIP  = new Gtk::Label ("Dirección IP");
$EtiquetaNumeroDireccionIP  = new Gtk::Label ("0.0.0.0");
$EtiquetaEstado  = new Gtk::Label ("Estado");
$EtiquetaTextoEstado  = new Gtk::Label ("");
$EtiquetaEntrada = new Gtk::Label ("Entrada");
$EtiquetaPaquetesEntrada = new Gtk::Label (0);
$EtiquetaSalida  = new Gtk::Label ("Salida");
$EtiquetaPaquetesSalida  = new Gtk::Label (0);
$EtiquetaEstado->set_justify ('left');
$EtiquetaEntrada->set_justify ('left');
$EtiquetaSalida->set_justify ('left');

# Definimos los botones
$BotonConectar = new Gtk::Button ("Conectar");
$BotonDesconectar = new Gtk::Button ("Desconectar");
$BotonCerrar = new Gtk::Button ("Cerrar");

# Añadimos los controles a la tabla
$Tabla->attach_defaults ($EtiquetaInterfaz, 0, 2, 0, 1);
$Tabla->attach_defaults ($BotonConectar, 0, 1, 1, 2);
$Tabla->attach_defaults ($BotonDesconectar, 1, 2, 1, 2);
$Tabla->attach_defaults ($EtiquetaEstado, 0, 1, 2, 3);
$Tabla->attach_defaults ($EtiquetaTextoEstado, 1, 2, 2, 3);
$Tabla->attach_defaults ($EtiquetaDireccionIP, 0, 1, 3, 4);
$Tabla->attach_defaults ($EtiquetaNumeroDireccionIP, 1, 2, 3, 4);
$Tabla->attach_defaults ($EtiquetaEntrada, 0, 1, 4, 5);
$Tabla->attach_defaults ($EtiquetaPaquetesEntrada, 1, 2, 4, 5);
$Tabla->attach_defaults ($EtiquetaSalida, 0, 1, 5, 6);
$Tabla->attach_defaults ($EtiquetaPaquetesSalida, 1, 2, 5, 6);
$Tabla->attach_defaults ($BotonCerrar, 0, 2, 6, 7);

# Mostramos los controles
$EtiquetaInterfaz->show();
$EtiquetaEstado->show();
$EtiquetaTextoEstado->show();
$EtiquetaDireccionIP->show();
$EtiquetaNumeroDireccionIP->show();
$EtiquetaEntrada->show();
$EtiquetaPaquetesEntrada->show();
$EtiquetaSalida->show();
$EtiquetaPaquetesSalida->show();
$BotonConectar->show();
$BotonDesconectar->show();
$BotonCerrar->show();

# Registramos las llamadas
$BotonConectar->signal_connect ("clicked", \&Conectar, "Conectar");
$BotonDesconectar->signal_connect ("clicked", \&Conectar, "Desconectar");

# Registramos las llamadas para cerrar la aplicación
$Ventana->signal_connect ("delete_event", \&CerrarAplicacion);
$BotonCerrar->signal_connect ("clicked", \&CerrarAplicacion);

# Añadimos la tabla a la ventana
$Ventana->add ($Tabla);

# Mostramos la caja
$Tabla->show();

# Mostramos la ventana
$Ventana->show();

# Activamos el temporizador
$Temporizador = Gtk->timeout_add (1000, \&Ver);

# El resto es cosa de GTK
main Gtk;

# Así que hasta aquí no se debería llegar nunca
exit (0);

#---------------------------------
# Funciones
#---------------------------------

#--------------------------------------------------------------------
# Función:  CerrarAplicacion()
# Objetivo: Cerrar la aplicación
#--------------------------------------------------------------------

sub CerrarAplicacion
  {
  Gtk->exit (0);
  return (0);
  }

#--------------------------------------------------------------------
# Función:  Conectar()
# Objetivo: Conectar o desconectar la interfaz
#--------------------------------------------------------------------

sub Conectar
  {
  # Recibimos los parámetros
  my ($Boton, $Texto) = @_;

  if ( $Texto eq "Conectar" )
    {
    $EtiquetaTextoEstado->set_text ("Conectando...");
    system ($OrdenConectar);
    }

  if ( $Texto eq "Desconectar" )
    {
    system ($OrdenDesconectar);
    $EtiquetaTextoEstado->set_text ("Desconectando...");
    }
  }

#--------------------------------------------------------------------
# Función:  Ver()
# Objetivo: Actualizar el estado del interfaz
#--------------------------------------------------------------------

sub Ver
  {
  my $Listado = "";        # Resultado de la orden
  my $OrdenCompleta = "";  # Orden completa para leer el estado

  # Averiguamos el estado del interfaz
  $OrdenCompleta = $OrdenConf . " " . $Interfaz . " 2>&1";
  $Listado = qx ($OrdenCompleta);

  # Comprobamos si tenemos conexión
  # (El método puede ser distinto según el tipo de conexión)
  if ( -e "/var/run/ip" ) # Tenemos conexión
    {
    # Calculamos el número de la dirección IP
    if ( $Listado =~ /addr:(.*)  P-t-P/ )
      {
      $EtiquetaTextoEstado->set_text ("Conectado");
      $EtiquetaNumeroDireccionIP->set_text ($1);
      }
    else # Esto no debería ocurrir nunca
      {
      $EtiquetaTextoEstado->set_text ("Error");
      $EtiquetaNumeroDireccionIP->set_text ("0.0.0.0");
      }
    }

  else # No tenemos conexión
    {
    $EtiquetaTextoEstado->set_text ("Desconectado");
    $EtiquetaNumeroDireccionIP->set_text ("0.0.0.0");
    }

  # Calculamos el número de paquetes de entrada
  if ( $Listado =~ /RX packets:(\d*) errors/ )
    { $EtiquetaPaquetesEntrada->set_text ($1); }

  # Calculamos el número de paquetes de salida
  if ( $Listado =~ /TX packets:(\d*) errors/ )
    { $EtiquetaPaquetesSalida->set_text ($1); }

  # Seguimos esperando que llamen otra vez a esta función
  return (1);
  }
