#!/usr/bin/perl -w

# The Vovida Software License, Version 1.0 
# 
# Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. The names "VOCAL", "Vovida Open Communication Application Library",
#    and "Vovida Open Communication Application Library (VOCAL)" must
#    not be used to endorse or promote products derived from this
#    software without prior written permission. For written
#    permission, please contact vocal\@vovida.org.
# 
# 4. Products derived from this software may not be called "VOCAL", nor
#    may "VOCAL" appear in their name, without prior written
#    permission of Vovida Networks, Inc.
# 
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
# NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
# NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
# IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR
# PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
# 
# ====================================================================
# 
# This software consists of voluntary contributions made by Vovida
# Networks, Inc. and many individuals on behalf of Vovida Networks,
# Inc.  For more information on Vovida Networks, Inc., please see
# <http://www.vovida.org/>.
#

# File: parseCalls
# usage:  parseCalls LOGFILE_NAME OUTPUT_DIRECTORY
#
# This program takes in a siph323csgw logfile as an input file.  It then
# groups the messages by call number, which  in turn are grouped by endpoints.
# The program can handle calls initiated from either direction: sip-to-h323, 
# or h323-to-sip.
# Each individual blocks of message will then be presented in a different
# file for analysis.  The name of each output file is made up of the timestamp,
# message type keyword (INVITE, setup, etc), and the direction of the message.
# Here's an example of the name of a file contain the message "setup":
# 000922-172708.566.setup.from.H323
#


# **************************************************************************
# Begin Main() 
#
#
# hash maps:
# @ipAddressToCallIdMap     - a map of call ID (key) to ip address (value)
# @callIdToEndPointMap      - a map of call ID (key) to enpoint id (value)
# @sipCallIdToH323CallIdMap - maps a sip callId (key) to an h323 callId (value)
# @msgToCallIdMap           - maps a message name (key) to its associated
#                             call id.  The value gets overwritten everytime
#                             the same message occurs.  So the value is 
#                             only good if you're referring to the last 
#                             occurrence of the message in question.


# check input arguments and setup output directory
#
if (!defined($ARGV[0]))
{
    print "usage: parseCalls LOGFILE_NAME OUTPUT_DIRECTORY";
    print "[default to current directory]\n";
    exit;
}

$infileName  = $ARGV[0];

if (defined($outputdir = $ARGV[1]))
{
    if ( $outputdir =~ /(\/$)/ )
    {
        $outputdir = $ARGV[1];  # ends with a slash
    }
    else
    {
        $outputdir = $ARGV[1]."/";  # add a slash to end
    }
    mkdir($outputdir,0777) unless (-d $outputdir);
}
else
{
   $outputdir = "";  # default to current directory
}

$errLog = $outputdir."parseCalls.errorLog";

# remove existing errLog
#
unlink($errLog);

open(ERRLOG, ">$errLog") || die("cannot open $errLog: $!");
print ERRLOG "*** Session for parsing $infileName ***\n";


# initialize global variables:
#
$RASaddress     = "";
$TCPaddress     = "";
$h245address    = "";
$cSeq           = "";
$callId         = "";
$timeStamp      = "";
$direction      = "";
$callOrigin     = "";  # is the call initiated by sip or h323?
$lastMsg        = "";

# are these messages written yet?
#
$ARQdumped       = 1;  # true
$INVITEdumped    = 1;  # true
$STATUSdumped    = 1;  # true
$CANCELdumped    = 1;  # true
$setupDumped     = 1;  # true
$alertingDumped  = 1;  # true


$leftBracelet  = 0;  # counter
$rightBracelet = 0;  # counter

open(IN,$infileName) || die("cannot open $infileName for reading: $!");
 
while ($line = <IN>)
{
    if ( $line =~ /CALLTRACE/ )
    {
        # ARQ
        if ( $line =~ / Message: ARQ/ )
        {
            $RASaddress = GetTargetAddress("ARQ");
            if ( !defined($RASaddress) )
	    {
                print "No address for ARQ.\n\n";
                die "\n";
	    }

            # extract message
            @retList = ExtractMsg("ARQ", "H225");
            ExtractReturnValuesFromRetList();  # retList gets modified

            # endpoint is not yet known, save buffer, defer write to ACF.
            #
            $ARQcseq           = $cSeq;
            $ARQcallOrigin     = $callOrigin;
            $ARQdirection      = $direction;
            $ARQtimeStamp      = $timeStamp;
            @ARQretList        = @retList;
 
            # suppress warning for unused items
            #
            Silence($ARQcseq, $ARQcallOrigin); 

            $ipAddressToCallIdMap{$RASaddress} = $callId;
            $msgToCallIdMap{"ARQ"}             = $callId;

            $ARQdumped = 0;  # false
            $lastMsg   = "ARQ";
        }
        # ACF
        elsif ( $line =~ / Message: ACF/ )
        {
            $RASaddress = GetTargetAddress("ACF");
            if ( !defined($RASaddress) )
	    {
                print "No address for ACF.\n\n";
                die "\n";
	    }

            @retList    = ExtractMsg("ACF", "H225");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $endPointId = GetEndpointId();     # from the next line
            $callId     = $ipAddressToCallIdMap{$RASaddress};
            $ACFcallId  = $callId;

            $callIdToEndPointMap{$callId} = $endPointId;

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".ACF",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);
            $lastMsg   = "ACF";

            # now that we have the endpoint, we can output the last ARQ
            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $ARQtimeStamp, 
                                   ".ARQ",
                                   $ARQdirection.".H323");

            $msgToCallIdMap{"ACF"} = $callId;
            DumpMsgToFile($fileName, @ARQretList);
            $ARQdumped = 1;  # true

            # dump any setup message that might be waiting for an endpoint
            #
            unless ($setupDumped)
	    {
                $endPointId = $callIdToEndPointMap{$setupCallId};        
                $fileName   = CreateFile($outputdir, 
                                         $endPointId,
                                         $setupCallId, 
                                         $setupTimeStamp, 
                                         ".setup",
                                         $setupDirection.".H323");

                DumpMsgToFile($fileName, @setupRetList);
                $setupDumped = 1;  # true
	    }

            # dump any alerting message that might be waiting for an endpoint
            #
            unless ($alertingDumped)
	    {
                $endPointId = $callIdToEndPointMap{$alertingCallId};        
                $fileName   = CreateFile($outputdir, 
                                         $endPointId,
                                         $alertingCallId, 
                                         $alertingTimeStamp, 
                                         ".alerting",
                                         $alertingDirection.".H323");

                DumpMsgToFile($fileName, @alertingRetList);
                $alertingDumped = 1;  # true
	    }

            # dump any INVITE message that might be waiting on 
            # a h323 callid from setup, assuming setup has happenned
            # when we got to ACF above
            #
            unless($INVITEdumped)
	    {
                $callId = $sipCallIdToH323CallIdMap{$INVITEsipCallId};
                $endPointId = $callIdToEndPointMap{$callId};

                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $INVITEtimeStamp, 
                                       ".INVITE",
                                       $INVITEdirection.".SIP");

                DumpMsgToFile($fileName, @INVITEretList);
                $INVITEdumped = 1;  # true
	    }

            # dump any STATUS message that might be waiting on 
            # a h323 callid from setup, assuming setup has happenned
            # when we got to ACF above
            #
            unless($STATUSdumped)
	    {
                $callId = $sipCallIdToH323CallIdMap{$STATUSsipCallId};
                $endPointId = $callIdToEndPointMap{$callId};

                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $STATUStimeStamp, 
                                       ".STATUS.$STATUSinfo",
                                       $STATUSdirection.".SIP");

                DumpMsgToFile($fileName, @STATUSretList);
                $STATUSdumped = 1;  # true
	    }

            # one last thing to do in ACF:
            # look for call id's that were inadvertently written out
            # to the unknownEndpoint directory because this ACF arrives
            # too late.  If found, move them all to this endpoint.
            #
            $unknownDir = $outputdir."unknownEndpoint/calls";
            if (-d $unknownDir )
	    {
                while ( defined($nextCallDir = <$unknownDir/*>) )
		{
                    $nextCallDir =~ m%calls/(\w+)%;
                    if ( $1 eq $ACFcallId )
		    {
                        $moveToDir 
                          = $outputdir."$endPointId/calls/$ACFcallId";

                        if (-d $moveToDir)
		        {
                            while ( defined($msgFile = <$nextCallDir/*>) )
			    {
                                $oldfilename = $msgFile;

                                # strip the leading directory components
                                #
                                $msgFile =~ s%.*/%%;

                                $moveToFile
                                  = $moveToDir."/$msgFile";

                                rename($oldfilename, $moveToFile);
                            }
                            rmdir($nextCallDir);
		        }
		    }
		}
	    }
        }    
        # setup
        elsif ( $line =~ / Message: setup/ )
        {
            # dump out any outstanding setup message so we
            # don't write over the buffer.  Usually when this happens,
            # we won't know the endpoint.
            #
            unless ($setupDumped)
	    {
                $endPointId = $callIdToEndPointMap{$setupCallId};        
                $fileName   = CreateFile($outputdir, 
                                         $endPointId,
                                         $setupCallId, 
                                         $setupTimeStamp, 
                                         ".setup",
                                         $setupDirection.".H323");

                DumpMsgToFile($fileName, @setupRetList);
                $setupDumped = 1;  # true
	    }

            @retList    = ExtractMsg("setup", "Q931");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $endPointId = $callIdToEndPointMap{$callId};
            if ( defined($endPointId) )
	    {
                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $timeStamp, 
                                       ".setup",
                                       $direction.".H323");

                DumpMsgToFile($fileName, @retList);
                $setupDumped = 1;  # true
	    }
            else
	    {
                # sip initiated this call, endpoint not yet known
                # save buffer, defer write to ACF
                #
                $setupCseq           = $cSeq;
                $setupCallOrigin     = $callOrigin;
                $setupCallId         = $callId;
                $setupDirection      = $direction;
                $setupTimeStamp      = $timeStamp;
                @setupRetList        = @retList;
 
                # suppress warning for unused items
                #
                Silence($setupCseq, $setupCallOrigin); 
                $setupDumped = 0;  # false
	    }

            # the last INVITE and STATUS messages may not have
            # been associated a h323 call id yet.  Do it here.
            unless ($INVITEdumped)
	    {
                $sipCallIdToH323CallIdMap{$INVITEsipCallId} = $callId;
	    }

            unless ($STATUSdumped)
      	    {
                $sipCallIdToH323CallIdMap{$STATUSsipCallId} = $callId;
	    }

            $msgToCallIdMap{"setup"} = $callId;
            $lastMsg = "setup";
        }    
        # callProceeding
        elsif ( $line =~ / Message: callProceeding/ )
        {
            @retList    = ExtractMsg("callProceeding", "Q931");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".callProceeding",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);

            $msgToCallIdMap{"callProceeding"} = $callId;
            $lastMsg = "callProceeding";
        }    
        # alerting
        elsif ( $line =~ / Message: alerting/ )
        {
            @retList    = ExtractMsg("alerting", "Q931");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $endPointId = $callIdToEndPointMap{$callId};
            if ( defined($endPointId) )
	    {
                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $timeStamp, 
                                       ".alerting",
                                       $direction.".H323");

                DumpMsgToFile($fileName, @retList);
                $setupDumped = 1;  # true
	    }
            else
	    {
                # sip initiated this call, endpoint not yet known
                # save buffer, defer write to ACF
                #
                $alertingCseq           = $cSeq;
                $alertingCallOrigin     = $callOrigin;
                $alertingCallId         = $callId;
                $alertingDirection      = $direction;
                $alertingTimeStamp      = $timeStamp;
                @alertingRetList        = @retList;
 
                # suppress warning for unused items
                #
                Silence($alertingCseq, $alertingCallOrigin); 
                $alertingDumped = 0;  # false
	    }

            $msgToCallIdMap{"alerting"} = $callId;
            $lastMsg = "alerting";
        }    
        # connect
        elsif ( $line =~ / Message: connect/ )
        {
            @retList    = ExtractMsg("connect", "Q931");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".connect",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);

            $msgToCallIdMap{"connect"} = $callId;
            $lastMsg = "connect";
        }    
        # INVITE
        elsif ( $line =~ / Message: INVITE/ )
        {
            # dump out any outstanding INVITE message so we
            # don't write over the buffer.  Usually when this happens,
            # we won't know the endpoint.
            #
            unless($INVITEdumped)
	    {
                $callId = $sipCallIdToH323CallIdMap{$INVITEsipCallId};
                $endPointId = $callIdToEndPointMap{$callId};

                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $INVITEtimeStamp, 
                                       ".INVITE",
                                       $INVITEdirection.".SIP");

                DumpMsgToFile($fileName, @INVITEretList);
                $INVITEdumped = 1;  # true
	    }

            # it is possible that there are messages left undumped
            # from the last call.  They can be CANCEL or STATUS
            # Dump them now.
            #
            unless($CANCELdumped)
	    {
                $callId = $sipCallIdToH323CallIdMap{$CANCELsipCallId};
                $endPointId = $callIdToEndPointMap{$callId};

                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $CANCELtimeStamp, 
                                       ".CANCEL",
                                       $CANCELdirection.".SIP");

                DumpMsgToFile($fileName, @CANCELretList);
                $CANCELdumped = 1;  # true
	    }

            unless($STATUSdumped)
	    {
                $callId = $sipCallIdToH323CallIdMap{$STATUSsipCallId};
                $endPointId = $callIdToEndPointMap{$callId};

                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $STATUStimeStamp, 
                                       ".STATUS.$STATUSinfo",
                                       $STATUSdirection.".SIP");

                DumpMsgToFile($fileName, @STATUSretList);
                $STATUSdumped = 1;  # true
	    }


            # INVITE message parsing starts here
            #
            @retList    = ExtractMsg("INVITE", "SIP");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            if ( ($callOrigin eq "SIP") && defined($callId) )
	    {
                # replace sip callid with h323 call id
                $finalCallId = $sipCallIdToH323CallIdMap{$callId};
	    }
            elsif ( ($callOrigin eq "H323") && defined($callId) )
	    {
                $finalCallId = $callId;
	    }
            else
	    {
                $finalCallId = "";  # undefined
	    }
          
            if ( defined($finalCallId) )
	    {
                # if $finnalCallId is good, the call must have been
                # initiated by H323, and we should know the endpoint.
                #
                $endPointId = $callIdToEndPointMap{$callId};

                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $finalCallId, 
                                       $timeStamp, 
                                       ".INVITE",
                                       $direction.".SIP");

                DumpMsgToFile($fileName, @retList);
                $INVITEdumped = 1;  # true
	    }
            elsif ( $callOrigin eq "SIP" )
	    {   
                # h323 call id not known yet, save buffer, defer write to setup
                #
                $INVITEcseq           = $cSeq;
                $INVITEcallOrigin     = $callOrigin;
                $INVITEsipCallId      = $callId;
                $INVITEdirection      = $direction;
                $INVITEtimeStamp      = $timeStamp;
                @INVITEretList        = @retList;
 
                # suppress warning for unused items
                #
                Silence($INVITEcseq, $INVITEcallOrigin); 

                $INVITEdumped = 0;  # false
	    }
            else
	    {
                print ERRLOG "Call ID undefined in INVITE\n";
	        if ( defined($timeStamp) )
	        {
                    print ERRLOG "time stamp: $timeStamp\n\n";
	        }
                else
                {
                    print ERRLOG "time stamp unknown\n\n";
                }
	    }

            $lastMsg = "INVITE";
        }
        # STATUS
        elsif ( $line =~ / Message: STATUS/ )
        {
            # dump out any outstanding STATUS message so we
            # don't write over the buffer.  Usually when this happens,
            # we won't know the endpoint.
            #
            unless($STATUSdumped)
	    {
                $callId = $sipCallIdToH323CallIdMap{$STATUSsipCallId};
                $endPointId = $callIdToEndPointMap{$callId};

                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $STATUStimeStamp, 
                                       ".STATUS.$STATUSinfo",
                                       $STATUSdirection.".SIP");

                DumpMsgToFile($fileName, @STATUSretList);
                $STATUSdumped = 1;  # true
	    }

            @retList    = ExtractMsg("STATUS", "SIP");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            # leave out REGISTER STATUS
            next if ( $cSeq eq "REGISTER");

            if ( $callOrigin eq "SIP" )
	    {
                # replace sip callid with h323 call id
                $finalCallId = $sipCallIdToH323CallIdMap{$callId};
	    }
            else  # callOrigin is H323
	    {
                $finalCallId = $callId;
	    }
          
            # at this point, we might not know the endpoint if the
            # call is sip-originated, eventhough it is already mapped
            # to an h323 call id.
            #
            $endPointId = $callIdToEndPointMap{$finalCallId};
            if ( defined($finalCallId) && defined($endPointId) )
	    {
                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $finalCallId, 
                                       $timeStamp, 
                                       ".STATUS.$statusInfo",
                                       $direction.".SIP");

                DumpMsgToFile($fileName, @retList);
                $STATUSdumped = 1;  # true
	    }
            elsif ( $callOrigin eq "SIP" )
	    {   
                # h323 call id not known yet, save buffer, defer write to setup
                #
                $STATUSinfo           = $statusInfo;
                $STATUScseq           = $cSeq;
                $STATUScallOrigin     = $callOrigin;
                $STATUSsipCallId      = $callId;
                $STATUSdirection      = $direction;
                $STATUStimeStamp      = $timeStamp;
                @STATUSretList        = @retList;
 
                # suppress warning for unused items
                #
                Silence($STATUScseq, $STATUScallOrigin); 

                $STATUSdumped = 0;  # false
	    }
            elsif ( $callOrigin eq "H323" )
	    {
                # at this point, we have no hope of finding the endpoint.
                # print the message to unknown endpoint
                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $finalCallId, 
                                       $timeStamp, 
                                       ".STATUS.$statusInfo",
                                       $direction.".SIP");

                DumpMsgToFile($fileName, @retList);
                $STATUSdumped = 1;  # true
            }
            else
	    {
                if ( defined($endPointId) )
		{
                    print ERRLOG "Endpoint ID for STATUS: $endPointId\n";
	        }
                else
		{
                    print ERRLOG "Cannot determine endpoint for STATUS\n";
		}

                if ( defined($finalCallId) )
		{
                    print ERRLOG "Call ID for STATUS: $finalCallId\n";
	        }
                else
		{
                    print ERRLOG "Call ID undefined in STATUS\n";
		}

	        if ( defined($timeStamp) )
	        {
                    print ERRLOG "time stamp: $timeStamp\n\n";
	        }
                else
                {
                    print ERRLOG "time stamp unknown\n\n";
                }
	    }

            $lastMsg = "STATUS";
        }
        # CANCEL
        elsif ( $line =~ / Message: CANCEL/ )
        {
            @retList    = ExtractMsg("CANCEL", "SIP");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            if ( $callOrigin eq "SIP" )
	    {
                # replace sip callid with h323 call id
                $finalCallId = $sipCallIdToH323CallIdMap{$callId};
	    }
            else  # callOrigin is H323
	    {
                $finalCallId = $callId;
	    }
          
            # at this point, we might not know the endpoint if the
            # call is sip-originated, eventhough it is already mapped
            # to an h323 call id.
            #
            $endPointId = $callIdToEndPointMap{$finalCallId};
            if ( defined($finalCallId) && defined($endPointId) )
	    {
                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $finalCallId, 
                                       $timeStamp, 
                                       ".CANCEL",
                                       $direction.".SIP");

                DumpMsgToFile($fileName, @retList);
                $CANCELdumped = 1;  # true
	    }
            elsif ( $callOrigin eq "SIP" )
	    {   
                #  h323 call id not known yet, save buffer, defer write to setup
                #
                $CANCELcseq           = $cSeq;
                $CANCELcallOrigin     = $callOrigin;
                $CANCELsipCallId      = $callId;
                $CANCELdirection      = $direction;
                $CANCELtimeStamp      = $timeStamp;
                @CANCELretList        = @retList;
 
                # suppress warning for unused items
                #
                Silence($CANCELcseq, $CANCELcallOrigin); 

                $CANCELdumped = 0;  # false
	    }
            elsif ( $callOrigin eq "H323" )
	    {
                # at this point, we have no hope of finding the endpoint.
                # print the message to unknown endpoint
                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $finalCallId, 
                                       $timeStamp, 
                                       ".CANCEL",
                                       $direction.".SIP");

                DumpMsgToFile($fileName, @retList);
                $CANCELdumped = 1;  # true
            }
            else
	    {
                if ( defined($endPointId) )
		{
                    print ERRLOG "Endpoint ID for CANCEL: $endPointId\n";
	        }
                else
		{
                    print ERRLOG "Cannot determine endpoint for CANCEL\n";
		}

                if ( defined($finalCallId) )
		{
                    print ERRLOG "Call ID for CANCEL: $finalCallId\n";
	        }
                else
		{
                    print ERRLOG "Call ID undefined in CANCEL\n";
		}

	        if ( defined($timeStamp) )
	        {
                    print ERRLOG "time stamp: $timeStamp\n\n";
	        }
                else
                {
                    print ERRLOG "time stamp unknown\n\n";
                }
	    }

            $lastMsg = "CANCEL";
        }
        # ACK
        elsif ( $line =~ / Message: ACK/ )
        {
            @retList    = ExtractMsg("ACK", "SIP");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            if ( ($callOrigin eq "SIP") )
	    {
                # replace sip callid with h323 call id
                $finalCallId = $sipCallIdToH323CallIdMap{$callId};
                $endPointId  = $callIdToEndPointMap{$finalCallId};
                
                if ( !defined($finalCallId) )
		{
                    $finalCallId = $callId;  # assign back to sip call id
                    $endPointId = "";        # endpoint unknown
		}
	    }
            else  # call origin is H323
	    {
                $finalCallId = $callId;
                $endPointId  = $callIdToEndPointMap{$finalCallId};
	    }
          
            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $finalCallId, 
                                   $timeStamp, 
                                   ".ACK",
                                   $direction.".SIP");

            DumpMsgToFile($fileName, @retList);

            $lastMsg = "ACK";
        }
        # BYE
        elsif ( $line =~ / Message: BYE/ )
        {
            @retList    = ExtractMsg("BYE", "SIP");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            if ( ($callOrigin eq "SIP") )
	    {
                # replace sip callid with h323 call id
                $finalCallId = $sipCallIdToH323CallIdMap{$callId};
                $endPointId  = $callIdToEndPointMap{$finalCallId};
                
                if ( !defined($finalCallId) )
		{
                    $finalCallId = $callId;  # assign back to sip call id
                    $endPointId = "";        # endpoint unknown
		}
	    }
            else  # call origin is H323
	    {
                $finalCallId = $callId;
                $endPointId  = $callIdToEndPointMap{$finalCallId};
	    }
          
            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $finalCallId, 
                                   $timeStamp, 
                                   ".BYE",
                                   $direction.".SIP");

            DumpMsgToFile($fileName, @retList);

            $lastMsg = "BYE";
        }
        # DRQ
        elsif ( $line =~ / Message: DRQ/ )
        {
            @retList    = ExtractMsg("DRQ", "RAS");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".DRQ",
                                   $direction.".H323");

            $msgToCallIdMap{"DRQ"} = $callId;
            DumpMsgToFile($fileName, @retList);

            $lastMsg = "DRQ";
        }    
        # DCF
        elsif ( $line =~ / Message: DCF/ )
        {
            @retList    = ExtractMsg("DCF", "RAS");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            if ( $lastMsg eq "DRQ" )
	    {
                $callId     = $msgToCallIdMap{$lastMsg};
                $endPointId = $callIdToEndPointMap{$callId};
	    }
            else
            {
                print "Cannot determine accompanying DRQ for DCF.\n";
                if ( defined($timeStamp) )
		{
                    print ERRLOG "time stamp: $timeStamp\n\n";
	        }
                else
                {
                    print ERRLOG "time stamp unknown\n\n";
                }
            }

            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".DCF",
                                   $direction.".H323");

            $msgToCallIdMap{"DCF"} = $callId;
            DumpMsgToFile($fileName, @retList);

            $lastMsg = "DCF";
        }    
        # Connection
        elsif ( $line =~ / Message: H\.245 Connection/ )
        {
            $TCPaddress = GetTargetAddress("Connection");
            @retList    = ExtractMsg("Connection", "TCP");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $ipAddressToCallIdMap{$TCPaddress} = $callId;

            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".Connection",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);
            $lastMsg = "Connection";
        }    
        # masterSlaveDetermination
        elsif ( $line =~ / Message: masterSlaveDetermination$/ )
        {
            $h245address = GetTargetAddress("masterSlaveDetermination");
            @retList     = ExtractMsg("masterSlaveDetermination", "H245");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $callId     = $ipAddressToCallIdMap{$h245address};
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".masterSlaveDetermination",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);
            $lastMsg = "masterSlaveDetermination";
        }    
        # masterSlaveDeterminationAck
        elsif ( $line =~ / Message: masterSlaveDeterminationAck/ )
        {
            $h245address = GetTargetAddress("masterSlaveDeterminationAck");
            @retList     = ExtractMsg("masterSlaveDeterminationAck", "H245");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $callId     = $ipAddressToCallIdMap{$h245address};
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".masterSlaveDeterminationAck",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);
            $lastMsg = "masterSlaveDeterminationAck";
        }    
        # terminalCapabilitySet
        elsif ( $line =~ / Message: terminalCapabilitySet$/ )
        {
            $h245address = GetTargetAddress("terminalCapabilitySet");
            @retList     = ExtractMsg("terminalCapabilitySet", "H245");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $callId     = $ipAddressToCallIdMap{$h245address};
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".terminalCapabilitySet",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);
            $lastMsg = "terminalCapabilitySet";
        }    
        # terminalCapabilitySetAck
        elsif ( $line =~ / Message: terminalCapabilitySetAck/ )
        {
            $h245address = GetTargetAddress("terminalCapabilitySetAck");
            @retList     = ExtractMsg("terminalCapabilitySetAck", "H245");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $callId     = $ipAddressToCallIdMap{$h245address};
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".terminalCapabilitySetAck",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);
            $lastMsg = "terminalCapabilitySetAck";
        }    
        # openLogicalChannel
        elsif ( $line =~ / Message: openLogicalChannel$/ )
        {
            $h245address = GetTargetAddress("openLogicalChannel");
            @retList     = ExtractMsg("openLogicalChannel", "H245");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $callId     = $ipAddressToCallIdMap{$h245address};
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".openLogicalChannel",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);
            $lastMsg = "openLogicalChannel";
        }    
        # openLogicalChannelAck
        elsif ( $line =~ / Message: openLogicalChannelAck/ )
        {
            $h245address = GetTargetAddress("openLogicalChannelAck");
            @retList     = ExtractMsg("openLogicalChannelAck", "H245");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $callId     = $ipAddressToCallIdMap{$h245address};
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".openLogicalChannelAck",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);
            $lastMsg = "openLogicalChannelAck";
        }    
        # endSessionCommand
        elsif ( $line =~ / Message: endSessionCommand/ )
        {
            $h245address = GetTargetAddress("endSessionCommand");
            @retList     = ExtractMsg("endSessionCommand", "H245");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified

            $callId     = $ipAddressToCallIdMap{$h245address};
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".endSessionCommand",
                                   $direction.".H323");

            DumpMsgToFile($fileName, @retList);
            $lastMsg = "endSessionCommand";
        }    
        # releaseComplete
        elsif ( $line =~ / Message: releaseComplete/ )
        {
            @retList    = ExtractMsg("releaseComplete", "Q931");

            # Set $direction, $timeStamp, $callId,
            # and $callOrigin (some maybe null).
            #
            ExtractReturnValuesFromRetList();  # retList gets modified
            $endPointId = $callIdToEndPointMap{$callId};

            $fileName = CreateFile($outputdir, 
                                   $endPointId,
                                   $callId, 
                                   $timeStamp, 
                                   ".releaseComplete",
                                   $direction.".H323");

            $msgToCallIdMap{"releaseComplete"} = $callId;
            DumpMsgToFile($fileName, @retList);

            $lastMsg = "releaseComplete";

            # if anyone still waiting for an endpoint, dump them now.
            #
            unless ($setupDumped)
	    {
                $endPointId = $callIdToEndPointMap{$setupCallId};        
                $fileName   = CreateFile($outputdir, 
                                         $endPointId,
                                         $setupCallId, 
                                         $setupTimeStamp, 
                                         ".setup",
                                         $setupDirection.".H323");

                DumpMsgToFile($fileName, @setupRetList);
                $setupDumped    = 1;  # true
	    }

            unless($INVITEdumped)
	    {
                $callId = $sipCallIdToH323CallIdMap{$INVITEsipCallId};
                $endPointId = $callIdToEndPointMap{$callId};

                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $INVITEtimeStamp, 
                                       ".INVITE",
                                       $INVITEdirection.".SIP");

                DumpMsgToFile($fileName, @INVITEretList);
                $INVITEdumped    = 1;  # true
	    }


            unless ($alertingDumped)
	    {
                $endPointId = $callIdToEndPointMap{$alertingCallId};        
                $fileName   = CreateFile($outputdir, 
                                         $endPointId,
                                         $alertingCallId, 
                                         $alertingTimeStamp, 
                                         ".alerting",
                                         $alertingDirection.".H323");

                DumpMsgToFile($fileName, @alertingRetList);
                $alertingDumped = 1;  # true
	    }

            unless($STATUSdumped)
	    {
                $callId = $sipCallIdToH323CallIdMap{$STATUSsipCallId};
                $endPointId = $callIdToEndPointMap{$callId};

                $fileName = CreateFile($outputdir, 
                                       $endPointId,
                                       $callId, 
                                       $STATUStimeStamp, 
                                       ".STATUS.$STATUSinfo",
                                       $STATUSdirection.".SIP");

                DumpMsgToFile($fileName, @STATUSretList);
                $STATUSdumped = 1;  # true
	    }
        }    
    }
}

# it is possible that a STATUS or a CANCEL may arrive after releaseComplete, 
# dump them now
#
unless($STATUSdumped)
{
    $callId = $sipCallIdToH323CallIdMap{$STATUSsipCallId};
    $endPointId = $callIdToEndPointMap{$callId};

    $fileName = CreateFile($outputdir, 
                           $endPointId,
                           $callId, 
                           $STATUStimeStamp, 
                           ".STATUS.$STATUSinfo",
                           $STATUSdirection.".SIP");

    DumpMsgToFile($fileName, @STATUSretList);
    $STATUSdumped = 1;  # true
}

unless($CANCELdumped)
{
    $callId = $sipCallIdToH323CallIdMap{$CANCELsipCallId};
    $endPointId = $callIdToEndPointMap{$callId};

    $fileName = CreateFile($outputdir, 
                           $endPointId,
                           $callId, 
                           $CANCELtimeStamp, 
                           ".CANCEL",
                           $CANCELdirection.".SIP");

    DumpMsgToFile($fileName, @CANCELretList);
    $CANCELdumped = 1;  # true
}

close(IN)     || die("cannot close $infileName: $!");

print ERRLOG "*** End of Session ***\n";
close(ERRLOG) || die("cannot close $errLog: $!");

#
# End Main() 
# **************************************************************************


# **************************************************************************
# function GetTargetAddress()
#
sub GetTargetAddress
{
    my($msgtype) = $_[0];
    if ( $line =~ /Address: AF_INET:(\w+.)(\w+.)(\w+.)(\w+:)(\w+)/ )
    {
        return ($1.$2.$3.$4.$5);
    }
    elsif ( $line =~ /Address: (UNKNOWN)/ )
    {
        return $1;
    }
    else
    {
        print ERRLOG "Cannot find Client Address for $msgtype\n";;
    }
} # end GetTargetAddress()
#
# **************************************************************************


# **************************************************************************
# function GetEndpointName()
#
sub GetEndpointId
{
    $line = <IN>;  # next line
    if ( $line =~ /endpointIdentifier=\"(.*?)\"/ )
    {
        return $1;
    }
    else
    {
        print ERRLOG "cannot find endpoint ID from ACF";
    }
} # end GetEndpointId()
#
# **************************************************************************


# **************************************************************************
# function: CreateFile()
# This function finds the message time stamp from the current line, 
# and form a file name by concatenating with the input arguments.
#
# input arguments as ordered:
# $_[0] - name of output directory.
# $_[1] - endpoint id.
# $_[2] - call id.
# $_[3] - message type (such as INVITE, setup, ACK, alerting, etc).
# $_[4] - message direction (example: "from.SIP", or "to.SIP", etc.
#
sub CreateFile
{
    # retrieve input parameters
    #
    my($outputDir, $endpt, $callId, $timeStamp, $msgType, $direction) = @_;

    # create endpoint directory unless it exists
    unless ( defined($endpt) )
    {
        $endpt = "unknownEndpoint";
    }
    $endptDir = $outputdir.$endpt."/";
    mkdir($endptDir,0777) unless (-d $endptDir);

    # create calls directory unless it exists
    $callsDir = $endptDir."calls/";
    mkdir($callsDir,0777) unless (-d $callsDir);

    # create call id directory unless it exists
    $callIdDir = $callsDir.$callId."/";
    mkdir($callIdDir,0777) unless (-d $callIdDir);
    my($outfileName) = $callIdDir.$timeStamp.$msgType.$direction;

    return $outfileName;
} # end CreateFile()
#
# **************************************************************************


# **************************************************************************
# function: ExtractReturnValuesFromRetList()
# This function extracts return parameters from global list @retList, which
# is returned by ExtractMsg().
#
sub ExtractReturnValuesFromRetList
{
    # Order is VERY IMPORTANT---last in first out
    #
    $statusInfo     = pop(@retList);
    $cSeq           = pop(@retList);
    $callOrigin     = pop(@retList);
    $direction      = pop(@retList);
    $timeStamp      = pop(@retList);
    $callId         = pop(@retList);
} # end ExtractReturnValuesFromRetList()
#
# **************************************************************************


# **************************************************************************
# function: DumpMsgToFile()
# This function writes to the given file with the content of the message 
# buffer.
#
# input arguments as ordered:
# $_[0] - output file name.
# $_[1] - a list of messages.
#
sub DumpMsgToFile
{
    my($fileName, @msgBuffer) = @_;

    open(OUT, ">$fileName") || die("cannot open $fileName: $!");

    foreach $bufline (@msgBuffer)
    {
        print OUT $bufline;
    }
} # end DumpMsgToFile()
#
# **************************************************************************


# **************************************************************************
# function: CountBracelets()
sub CountBracelets
{
        $leftBracelet++  if ( $line =~ /{$/ );
	$rightBracelet++ if ( $line =~ /}$/ );
} # end CountBracelets()
#
# **************************************************************************


# **************************************************************************
# function: CountQ931Bracelets()
sub CountQ931Bracelets
{
        $leftBracelet++  if ( $line =~ /\s{$/ );
	$rightBracelet++ if ( $line =~ /}$/ );
} # end CountQ931Bracelets()
#
# **************************************************************************


# **************************************************************************
# function resetBraceletCounters()
#
sub ResetBraceletCounters
{
   $leftBracelet  = 0;
   $rightBracelet = 0;
}
#
# **************************************************************************


# **************************************************************************
# function Silence()
# This function has no particular function but to suppress warning
# message from the compiler for unused scalars.
#
sub Silence
{
}
#
# **************************************************************************


# **************************************************************************
# function GetQ931Msg()
# This function extracts only the Q931 message block and write it to the
# message buffer.
#
sub GetQ931Msg
{
    # find the first left bracelet
    $line = <IN>;
    while ( !($line =~ /{$/) )
    {
        push(@msgBuffer,$line);
        $line = <IN>;
    }
    CountQ931Bracelets();        # after every new line
    push(@msgBuffer,$line);  # found the first left bracelet

    # extract body of message
    #
    while ($leftBracelet != $rightBracelet)
    {
	$line = <IN>;        # IN filehandle from main
        CountQ931Bracelets();    # after every new line

        push(@msgBuffer, $line);
    }
} # end GetQ931Msg()
#
# **************************************************************************


# **************************************************************************
# function: ExtractH323CallId()
sub ExtractH323CallId
{
    my($msg) = $_[0];
    my($callID) = "";
    my($lineCount) = 1;
    {
        # skip 2 lines to the 16 octets call id
        while ( $lineCount < 3 )
        {
            push(@msgBuffer,$line);
            $line = <IN>;

            # don't count bracelets within call id
            #
            CountBracelets() unless ($lineCount == 2);
            $lineCount++;
        }

        # extract 16 octets call id
        if ( $line =~ /(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s(\w+)\s/ )
        {
            $callID = $1.$2.$3.$4.$5.$6.$7.$8.$9.$10.$11.$12.$13.$14.$15.$16;
        }
        else
	{
            die "failed to find H323 callIdentifier for $msg.";
        }
    }
    return $callID;

} # end ExtractH323CallId()
#
# **************************************************************************


# **************************************************************************
# function: GetOmniCallId()
# The call id field of a sip message is ominous because it can contain only
# the sip call id, or it can contain the sip call id appended with an h323
# call id.  This function differentiates the two and extracts the sip call
# id if the call id field contains only the sip call id, or it extracts
# the h323 call id if that field contains a both sip and h323 call id's.
#
sub GetOmniCallId
{
    my($callid) = "";
    my($callOrigin) = "";

    if ( $line =~ /\b\.(\w+)@/ )
    {
        $callid     = $1;
        $callOrigin = "H323";
    }
    elsif ( $line =~ /Call-ID: (\w+.*)@\b/ )
    {
        $callid     = $1;
        $callOrigin = "SIP";
    }
    else
    {
        die "Failed to find call id.\n";
    }
    return ($callid, $callOrigin);

} # end GetOmniCallId()
#
# **************************************************************************


# **************************************************************************
# function: ExtractMsg()
# This function extracts text that are by the outermost {} for a given
# message.  Each message is unique and is written to a separate file.
#
# input arguments as order:
# $_[0] - message type (such as ARQ, INVITE, alerting, etc).
# $_[1] - protocol (such as H323, SIP, Q932, etc).

#
# list of output items as ordered:
# @msgBuffer  - 
# $callId     - call identifier in the message.
# $timeStamp  - time of the message transmission as tagged by translator.
# $direction  - transmission direction w/respect to the translator(to/from).
# $callOrigin - where the call is initiated, sip or h323.
# $cseq       - Cseq, relevant only to sip message
# $statusInfo - description of STATUS, relevant only to STATUS message
#

sub ExtractMsg
{
    my($msgType, $protocol) = @_;
    
    my($lineCount)   = 1;
    my($callId)      = "";
    my($cseq)        = "";
    my($callOrigin)  = "";
    my($timeStamp)   = "";
    my($statusInfo)  = "";

    local(@msgBuffer)   = "";

    # extract timestamp, we're in first line and should have the timeStamp
    if ( $line =~ /(\b0\w+.)(\w+.)(\w+)/ )
    {
        $timeStamp = $1.$2.$3;  # add them up
    }
    else
    {
       die("cannot match for time stamp pattern.\n");
    }

    # determine direction of message
    if ( $line =~ /Outbound/ )
    {
        $direction = ".to";
    }
    elsif ( $line =~ /Inbound/ )
    {
        $direction = ".from";
    }

    # find the first left bracelet
    while ( !($line =~ /{$/) )
    {
        push(@msgBuffer,$line);
        $line = <IN>;
    }
    CountBracelets();        # after every new line
    push(@msgBuffer,$line);

    # extract body of message
    #
    while ($leftBracelet != $rightBracelet)
    {
	$line = <IN>;        # IN filehandle from main
        CountBracelets();    # after every new line
     
        if ( ($msgType eq "ARQ")             || 
             ($msgType eq "setup")           ||
             ($msgType eq "callProceeding")  ||
             ($msgType eq "alerting")        ||
             ($msgType eq "connect")         ||
             ($msgType eq "Connection")      ||
             ($msgType eq "releaseComplete") ||
             ($msgType eq "DRQ")    
           )
        {
            if ( $line =~ /callIdentifier/ )
	    {
                $callId = ExtractH323CallId();
	    }
        }
        elsif ( ($msgType eq "INVITE") ||
                ($msgType eq "STATUS") ||
                ($msgType eq "CANCEL") ||
                ($msgType eq "ACK"   ) ||
                ($msgType eq "BYE"   )
              )
        {
            if ( $line =~ /Call-ID: / )
	    {
                ($callId, $callOrigin) = GetOmniCallId();
	    }
            elsif ( $line =~ /^CSeq:\s\d\s(\w+)/ )
	    {
                $cseq = $1;
	    }

            if ($msgType eq "STATUS")
	    {
                # get the status info from the SIP line
                #
                if ($line =~ /^SIP/)
                {
                    $statusInfo = $line;
                    $statusInfo =~ s/\s//g;
                    $statusInfo =~ s/SIP\/\d\.\d//;
                }
	    }
	}
        push(@msgBuffer,$line);
    }
    ResetBraceletCounters();

    GetQ931Msg() if ( $protocol eq "Q931" );
    ResetBraceletCounters();

    return (@msgBuffer, $callId, $timeStamp,
            $direction, $callOrigin, $cseq, $statusInfo);
} # end ExtractMsg
#
# **************************************************************************

