#!/usr/bin/perl

$CurrentHour='';
while(<>)
{
#    "2006-08-04T14:28:20.542522Z":42:INCOMING:INFO:sukothai.pingtel.com:SipClient-10:B777DBA0:SipProxy:"Read SIP message:\n----Remote Host:10.1.1.20---- Port: 53863----\nREGISTER sip:sukothai.pingtel.com SIP/2.0\r\nVia: SIP/2.0/TCP 10.1.1.20:53863;branch=z9hG4bK-20039ed44ec472a05c4034d33428068a\r\nTo: sip:222@sukothai.pingtel.com\r\nFrom: Sip Send <sip:sipsend@10.1.1.20>;tag=3e4776f6\r\nCall-ID: 85af55620b92196425cdd4f8c3289448@10.1.1.20\r\nCseq: 1 REGISTER\r\nMax-Forwards: 20\r\nUser-Agent: sipsend/0.02\r\nDate: Fri, 4 Aug 2006 14:28:20 GMT\r\nContent-Length: 0\r\n\r\n====================END====================\n"

    if ( m|^"(\d{4}-\d{2}-\d{2}T\d{2}):| ) # " get time stamp (through the hour)
    {
        &record($1);

        if ( s|^.*:INCOMING:INFO:.*:SipClient-\d+:.*:\"Read SIP message:\\n----Remote Host:\d+\.\d+\.\d+\.\d+---- Port: \d+----\\n|| )
        {
            &countMessage('first');
        }
        if ( s|^.*:INCOMING_PARSED:DEBUG:.*:SipClient-\d+:.*:\"Received duplicate message\\n|| )
        {
            &countMessage('duplicate');
        }
    }
}

# flush the remaining counts by recording a null timestamp
&record('');

# determine the width needed for the method column
foreach ( keys %Messages )
{
    $maxMethodWidth = length
        if ( length > $maxMethodWidth );
}
$maxMethodWidth += 4;

# build up the format lines 
foreach ( sort keys %Count )
{
    /\d{4}-(\d{2}-\d{2})T(\d{2})/;

    $Dates  .= "   $1";
    $Hours  .= "      $2";
    $Bars   .= ' -------';
    $Counts .= ' @######';
    $Data   .= ",\$Count{'$_'}->{\$_}";
}
$DateLine = 'Method' . ( ' ' x ( $maxMethodWidth - length('Method') ) ) . $Dates . "\n";
$HourLine = ' ' x ($maxMethodWidth - length('detail')) . 'detail' . $Hours . "\n";
$BarLine  = '-' x $maxMethodWidth . $Bars . "\n";
$CountLine = '@' . ( '>' x ( $maxMethodWidth - 1 ) ) . $Counts . "\n";
$DataLine =  '$RowName' . $Data . "\n";
eval "format STDOUT_TOP =\n$DateLine$HourLine$BarLine.\n";
eval "format STDOUT     =\n$CountLine$DataLine.\n";

# construct the message type rows
@Rows = 
    sort 
    grep ! m/(Messages| Duplicates| Requests| Responses)/, 
    ( keys %Messages );
# prepend the global count rows
unshift @Rows, ' Responses';
unshift @Rows, ' Requests';
unshift @Rows, ' Duplicates';
unshift @Rows, 'Messages';

## print rows
foreach ( @Rows )
{
    if ( ! m/ / )
    {
        # left justify unqualified method names
        $RowName = $_ . ( ' ' x ( $maxMethodWidth - length($_) ) );
    }
    else
    {
        # left justify unqualified method names
        $RowName = $_;
    }


    write;
}

sub countMessage
{
    my ( $type ) = shift;

    $Messages++;

    if ( $type eq 'duplicate' )
    {
        $Duplicates++;
    }

    if ( m|^(\w+)\s+\S+\s+SIP/2.0| ) # request
    {
        $Requests++;

        $Method = $1;
        $Method =~ tr/a-z/A-Z/;

        if ( $Method =~ m/\A(SUBSCRIBE|NOTIFY|PUBLISH)\Z/i )
        {
            m|\\nEvent:\s*([\w-]+)|i;
            $Package = ' ' . ( $1 || '(unknown)' );
            $Messages{"$Method$Package"}++ unless $type eq 'duplicate';
        }
        
        if ( $type eq 'duplicate' )
        {
            $Messages{$Method}--;
            $Method .= ' (duplicate)';
        }

        $Messages{$Method}++;
    }
    elsif ( m|^SIP/2.0\s+(\d+).*\\n(?:Cseq\|I):\s*\d+\s+(\w+)|i ) # response
    {
        #SIP/2.0 202 Accepted\r\nExpires: 7200\r\nFrom: \"Leto Atriedes\" <sip:8005551181@sipx-socal01.example.com>;tag=4F9D0F0A-8A356FB1\r\nTo: <sip:8005551181@sipx-socal01.example.com>;tag=833061270\r\nCall-Id: c7c10d1e-9217f46c-19e5112b@10.0.35.201\r\nCseq: 2 SUBSCRIBE\r\nVia: SIP/2.0/TCP 10.0.4.87;branch=z9hG4bK-2c97076e7747d6dc0a07a947c714cb22\r\nVia: SIP/2.0/UDP 10.0.35.201:5060;branch=z9hG4bK93e53ec764298C78\r\nContact: sip:8005551181@sipx-socal01.example.com\r\nDate: Wed, 09 Aug 2006 18:00:00 GMT\r\nAllow: INVITE, ACK, CANCEL, BYE, REFER, OPTIONS, NOTIFY, SUBSCRIBE\r\nUser-Agent: sipX/3.0.30 (Linux)\r\nAccept-Language: en\r\nSupported: sip-cc-01, timer\r\nContent-Length: 0\r\n\r\n====================END====================\n"
        $Code = $1;
        $Method = $2;

        $Responses++;
        $Method =~ tr/a-z/A-Z/;

        $Method .= ' ' . $Code;

        if ( $type eq 'duplicate' )
        {
            $Messages{$Method}--;
            $Method .= ' (duplicate)';
        }

        $Messages{$Method}++;
    }

}

sub record
{
    my ( $hour ) = shift;

    if ( $CurrentHour && ( $CurrentHour ne $hour ) )
    {
        $Count{$CurrentHour}->{'Messages'} += $Messages;
        $Messages = 0;

        $Count{$CurrentHour}->{' Duplicates'} += $Duplicates;
        $Duplicates = 0;

        $Count{$CurrentHour}->{' Requests'} += $Requests;
        $Requests = 0;

        $Count{$CurrentHour}->{' Responses'} += $Responses;
        $Responses = 0;

        foreach ( keys %Messages )
        {
            $Count{$CurrentHour}->{$_} += $Messages{$_};
            $Messages{$_} = 0;
        }
    }

    $CurrentHour = $hour;
}

