#!/usr/bin/perl

use strict;
use POSIX;
use Net::Pcap;
use NetPacket::Ethernet;
use NetPacket::IP;
use NetPacket::TCP;
use NetPacket::UDP;
use Socket;
use IO::Socket;

my $server = IO::Socket::INET->new(
  Proto     => 'udp',
  PeerPort => 10000,
  PeerAddr    => 'led-wall' )
or die "can't setup server";

my @led_timer;

my $err;

my $dev = "eth1";
unless (defined $dev) {
    $dev = Net::Pcap::lookupdev(\$err);
    if (defined $err) {
        die 'Unable to determine network device for monitoring - ', $err;
    }
}

my ($address, $netmask);
my $object = Net::Pcap::open_live($dev, 1500, 0, 0, \$err);

my $filter;
Net::Pcap::compile(
    $object, 
    \$filter,
    #make your private network range in the filter below
    '(not src net 192.168.0.0/16)',
    0, 
    $netmask
) && die 'Unable to compile packet capture filter';

Net::Pcap::setfilter($object, $filter) &&
  die 'Unable to set packet capture filter';

unless (defined $object) {
  die 'Unable to create packet capture on device ', $dev, ' - ', $err;
}

#print $server "ticklex";

Net::Pcap::loop($object, -1, \&packets, $server) ||
  die 'Unable to perform packet capture';

sub led_timeout {
  my ($user_data, $pixel) = @_;
  $led_timer[$pixel] = time() + 30;

  for (my $i=0; $i<1024; $i++) {
    if (($led_timer[$i] < time()) && ($led_timer[$i]>0)) {
      print $user_data "R:$i,0";
      print $user_data "G:$i,0";
      print $user_data "B:$i,0";
      $led_timer[$i] = 0;
    }
  }
}

sub ip2dec ($) {
    unpack N => pack CCCC => split /\./ => shift;
}

sub packets {
  my ($user_data, $header, $packet) = @_;
  my $ether_data = NetPacket::Ethernet::strip($packet);
  my $ip = NetPacket::IP->decode($ether_data);
  my $num;
  my $pixel;
  my $intensity;
  if($ip->{proto} == 6) {
    my $tcp = NetPacket::TCP->decode($ip->{'data'});
    if ($tcp) {
      $num = $tcp->{'src_port'} / 64;
      $pixel = floor($num);
      $intensity = floor((((sprintf("%.2f",($num-$pixel))*100)) * 256) / 100);
      print $user_data "R:$pixel,$intensity";
    }
  } elsif ($ip->{proto} == 17) {
    my $udp = NetPacket::UDP->decode($ip->{'data'});
    if ($udp) {
      $num = $udp->{'src_port'} / 64;
      $pixel = floor($num);
      $intensity = floor((((sprintf("%.2f",($num-$pixel))*100)) * 256) / 100);
      print $user_data "G:$pixel,$intensity";
    }
  } else {
    $num = ip2dec($ip->{'src_ip'}) / 4194304;
    $pixel = floor($num);
    $intensity = floor((((sprintf("%.2f",($num-$pixel))*100)) * 256) / 100);
    print $user_data "B:$pixel,$intensity";
  }
  led_timeout($user_data, $pixel);
}
