callflowcanvas.pm

来自「radius协议源码÷The Radius Stack will connect」· PM 代码 · 共 1,127 行 · 第 1/3 页

PM
1,127
字号
package CallFlowCanvas;use strict;use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);require Exporter;use Tk;use Carp;use constant DEBUG                 => 0;use constant DEBUG_GUI             => 0;use constant DEBUG_SIP_MESSAGES    => 0;use constant DEBUG_LOGICAL_NAMES   => 0;use constant DEBUG_SNAPSHOTS       => 0;use constant UEBER_DEBUG_SNAPSHOTS => 0;use constant DEBUG_POSTSCRIPT      => 0;@ISA = qw (Exporter AutoLoader);@EXPORT = qw ( add_sip_message change_snapshot_preferences readjust_width );@EXPORT_OK = qw ( get_call_id _construct_canvas );$VERSION = '0.01';# Preloaded methods go here.# Autoload methods go after =cut, and are processed by the autosplit program.1;#__END__#Protected methods and class variables#!#!#!{    my $batch_process = 0;    #Side-effected by &$_draw_arrow    my %settings = (arrow_start_vposition    => 15,		    canvas_default_font      => '-Adobe-Courier-Medium-R-Normal--12-120-75-75-M-70-ISO8859-1',		    break_font               => '-Adobe-Courier-Medium--Normal--24-120-75-75-M-70-ISO8859-1',		    canvas_width             => 500, #minimum; adjusted below		    canvas_height            => 400, #minimum; adjusted below		    space_between_arrows     => 40,		    server_start_hposition   => 50,		    server_vposition         => 20,		    space_between_servers    => 50,		    server_box_hsize         => 170, #! Later, scale to text of name		    server_box_vsize         => 50,		    break_width              => 10,		    break_offset_space       => 15		    );        my %colors =   (INVITE     => 'brown4', 		    ACK        => 'green3',		    OPTIONS    => 'orange',		    BYE        => 'darkgoldenrod4',		    REGISTER   => 'purple',		    '1xx'      => 'black',		    '200'      => 'forest green',		    '3xx'      => 'blue',		    '4xx'      => 'red',		    '5xx'      => 'dark red',		    sip_header_name    => 'black',		    sip_header_value   => 'blue',		    sdp_header_name    => 'dark slate grey',		    sdp_header_value   => 'green',		    canvas_background  => 'light yellow',		    canvas_foreground  => 'black',		    server_box_fill    => 'white',		    server_box_outline => 'black',		    		    break              => 'black');    #parameters that control the Postscript printing functionality    #These are just defaults; if the user has a .tricorderrc, preferences    #are loaded from there and passed in to the constructor, overriding    #these values.    my %default_snapshot_preferences = (file           => 'call_flow.eps',					colormode      => 'mono',					scaling_factor => 1,					rotate         => 1, #landscape orientation					page_length    => 1100, #pixels					page_width     => 800, #pixels					);    my ($page_width, $page_length);    #Protected methods    my $_set_initial_positions =    sub    {	my ($self) = @_;	$self->{arrow_vposition} = $settings{server_box_vsize}                                 + $settings{server_vposition}                                 + $settings{arrow_start_vposition};	$self->{arrow_number} = 1;	$self->{server_box_hposition} = $settings{server_start_hposition};    };    #Apply the user's choice of heuristics to the recipient or sender of a    #SIP message to guess whether it is coming from a server or just from    #some random endpoint.    my $_looks_like_a_server =    sub    {	my ($self, $message, $endpoint) = @_;	my $heuristic = $self->{heuristic} || '';	if (ref $message ne 'Telephony::SipMessage')	{	    warn "\&\$_looks_like_a_server got an argument of type " . ref $message		. "\n, which is not a SipMessage.  Skipping...";	    return;	}    	#default:  Treat everything as a server.	return 1 if ($heuristic eq 'assume-server');	#another option:  Discriminate between servers and endpoints based on	#their IPs	if ($heuristic eq 'use-vovida-ip-numbering-scheme')	{	    my $ip = $message->{"${endpoint}_ip"};	    	    #Check to see if its IP fits the Vovida SIP server numbering	    #scheme.	    $ip =~ m|\.(.+)$|m;  #Look at the	    my $last_octet = $1; #last octet only.	    if ($last_octet == 180 || #a UA marshal, by Vovida conventions		$last_octet == 200 || #a redirect server, by Vovida		                      #conventions		$last_octet == 110 || #a 5300 marshal, by Vovida conventions		$last_octet == 210)   #a 5300, by Vovida conventions	    {		return 1;	    }	    else	    {		return 0;	    }	}	#another option:  Be really clever and look at the actual SIP message.	elsif ($heuristic eq 'use-sip-hints')	{	    my $ip = $message->{"${endpoint}_ip"};	    if ($message->{sip_uri} =~ /@(\.+?):/)	    {		#works for both hostnames and IPs...		my $ip_from_URI = inet_ntoa (gethostbyname ($1));				if ($endpoint eq 'destination')		{		    #Check to see if the IP from the SIP-URI matches the		    #destination IP; if so, it's an endpoint, not a server.		    if ($ip_from_URI eq $ip) { return 0; }		    else { return 1; }		}		else #by deduction, ($endpoint eq $SOURCE)		{		    #Check to see if the host in the SIP-URI matches		    #the From header;		    #if so, it's an endpoint, not a server		    my $ip_from_From = $message->get_sip_header ('From');		    if ($ip_from_From eq $ip) { return 0; }		    else { return 1; }		}	    }	    else	    {		warn "Got a SIP message with an invalid SIP-URI:  \n"		    . Data::Dumper->Dump ([ $message ]);	    }	}	else	{	    #Default:  Assume it's a server, just to be safe.	    return 1;	}    };    my $_draw_server_box =    sub    {	my ($self, $server) = @_;	my $canvas = $self->{canvas};	print "in \&\$_draw_server_box\n" if DEBUG;	#! Later, make customizable through --naming-scheme option	my $server_name = $server->{logical_name}                       || $server->{ip} . ':' . $server->{port};	print "server $server_name is\n" . Data::Dumper->Dump ([ $server ]) if DEBUG_SIP_MESSAGES;	my $x1 = $self->{server_box_hposition};	my $y1 = $settings{server_vposition};	my $x2 = $self->{server_box_hposition} + $settings{server_box_hsize};	my $y2 = $y1 + $settings{server_box_vsize};	print "Drawing box from ($x1, $y1) to ($x2, $y2) (for $server_name)\n" if DEBUG;	my $box = $canvas->createRectangle	                    ($x1,			     $y1,			     $x2,			     $y2,			     fill    => $colors{server_box_fill},			     outline => $colors{server_box_outline},			     tags    => [ 'server_box' ]			     );    	if (DEBUG)	{	    my @coords = $canvas->bbox (\$box);	    print "Drew box with bounding coordinates " . @coords;	}	my $horizontal_midpoint = $x1 + $settings{server_box_hsize} / 2;	my $vertical_midpoint   = $y1 + $settings{server_box_vsize} / 2;		#Record the horizontal coordinate of the _center_ of the server box	#so &$_draw_arrow can recall it later.	$server->{hposition} = $horizontal_midpoint;	$canvas->createText ($horizontal_midpoint,			     $vertical_midpoint,			     text    => $server_name,			     #! width   => $settings{server_hsize},			     fill    => $colors{server_box_outline},			     font    => $settings{canvas_default_font},			     justify => 'center',			     tags    => 'server_label'			     );	my $bottom_of_the_canvas = $canvas->cget ('-height');	$self->{server_box_hposition} += ($settings{server_box_hsize}					  + $settings{space_between_servers});    };    my $_draw_lines_under_server_boxes =    sub    {	my ($self, $bottom_of_the_canvas) = @_;	my $canvas = $self->{canvas};	map	{	    $canvas->createLine ($_->{hposition},				 $settings{server_vposition}				 + $settings{server_box_vsize},				 $_->{hposition},				 $bottom_of_the_canvas,				 fill   => $colors{server_box_outline},				 smooth => 1,				 tags   => [ 'vertical_line' ]				 );	} @{$self->{server_list}};    };    #Resize the canvas to make it large enough for all that has been    #drawn on it.    my $_resize_canvas =    sub    {	my ($self) = @_;	my $canvas = $self->{canvas};	my ($x1, $y1, $x2, $y2) = my @bounding_coordinates = $canvas->bbox ('all');	print "Resizing canvas:  ($x1, $y1), ($x2, $y2)\n" if DEBUG;	$canvas->configure (scrollregion => \@bounding_coordinates);	&$_draw_lines_under_server_boxes ($self, $y2); #bottom of the canvas    };    my $_handle_new_servers =    sub    {	my ($self, $message, $endpoint, $draw) = @_;	#Add the source and destination servers if they do not already	#exist.	my $ip          = $message->{"${endpoint}_ip"} || '';	my $port        = $message->{"${endpoint}_port"};	my $ip_and_port = $ip . ':' . $port;	print "Examining server $ip:$port\n" if DEBUG_SIP_MESSAGES;	if ($ip &&            ! exists ($self->{server_hash}->{$ip_and_port})	    && &$_looks_like_a_server ($self, $message, $endpoint))	{	    my $logical_name = undef;	    if ($self->{logical_names})	    {		$logical_name = $self->{server_map}->{$ip_and_port};		print "Got logical name $logical_name for server $ip_and_port\n" if DEBUG_LOGICAL_NAMES;	    }	    my $server = Telephony::SipServer->new ($ip,						    $port,						    $logical_name);	    $self->{server_hash}->{$ip_and_port} = $server;	    push @{$self->{server_list}}, $server;	    print "Found new server (IP $ip, port $port):\n"		. Data::Dumper->Dump ([ $server ]) if DEBUG;	    &$_draw_server_box ($self, $server);	    &$_resize_canvas ($self);	}    };    my $_draw_header_balloons =    sub    {	my ($self, $message_number, $message, $x, $y) = @_;	my $canvas = $self->{canvas};	print "After call to \$&_draw_header_balloons, \$message_number is $message_number\n" if DEBUG;	defined $message->{sip_headers}        or return;	my $sip_balloon = FancyBalloon->new ($message->{sip_headers},					     $colors{sip_header_name},					     $colors{sip_header_value},					     $canvas);	if (! defined $sip_balloon)	{	    warn "FancyBalloon->new returned undef; there is no SIP balloon to display.";	    return;	}	print "Constructed a SIP FancyBalloon:\n" . Data::Dumper->Dump ([ $sip_balloon ]) if DEBUG;    	$sip_balloon->title ("$message_number. $message->{reqres}");	#! $sip_balloon->place (-x => $x, -y => $y + 5); #in $self->{canvas},	#its parent	#! Ouch, that doesn't work.  I'll have to fiddle with the window	#! manager!	if (defined $message->{sdp_headers})	{	    my $sdp_balloon = FancyBalloon->new ($message->{sdp_headers},						 $colors{sdp_header_name},						 $colors{sdp_header_value},						 $canvas);	    	    if (! defined $sdp_balloon)	    {		warn "FancyBalloon->new returned undef; there is no SDP balloon to display.";		return;	    }		    print "Constructed an SDP FancyBalloon:" . Data::Dumper->Dump ([ $sdp_balloon ]) if DEBUG;	    $sdp_balloon->title ("$message_number. $message->{reqres}");	    #! $sdp_balloon->place (-x => $x,	    #!                      -y => $y + 5 + $sip_balloon->height());	    #in $canvas, its parent	    #! Ouch, that doesn't work.  I'll have to fiddle with the window manager!	}    };    my $_get_arrow_color =    sub    {	my ($self) = @_;	my $color;	my $reqres = shift();        print "Getting color" if (DEBUG || DEBUG_SIP_MESSAGES);        print " for $reqres arrow..." if DEBUG_SIP_MESSAGES;        print "\n" if (DEBUG || DEBUG_SIP_MESSAGES);        #Response codes:  Match on the first digit (which indicates the        #general type of response)        if ($reqres =~ /^(\d)/)        {            $color = $colors{(grep /$1/, (keys %colors))[0]};        }        #Requests:  Match on the whole name        else        {	    $color = $colors{$reqres};        }	

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?