#!/usr/bin/env python

'''Show current RTP sessions'''

## add the modules subdir to the import search path
import sys, os
sys.path[1:1] = [os.path.realpath((os.path.dirname(sys.argv[0]) or '.') + '/modules')]
del os


import re
versionLine = re.compile(r'''version\s+
                             (?P<version>[^\s]+)           # proxy version
                             ''', re.VERBOSE)

summaryLine = re.compile(r'''proxy\s+
                             (?P<sessions>\d+)             # session count
                             \s+ 
                             (?P<traffic1>\d+)             # traffic from peer1
                             /
                             (?P<traffic2>\d+)             # traffic from peer2
                             /
                             (?P<traffic>\d+)              # traffic relayed
                             ''', re.VERBOSE)

sessionLine = re.compile(r'''session\s+
                             (?P<id>\S+)                   # session id
                             \s+ 
                             (?P<from>\S+)                 # from address
                             \s+
                             (?P<to>\S+)                   # to address
                             \s+
                             (?P<callerAgent>\S+)          # caller agent
                             \s+
                             (?P<calledAgent>\S+)          # called agent
                             \s+
                             (?P<duration>\d+)             # session duration
                             ''', re.VERBOSE)

streamLine = re.compile(r'''stream\s+
                            (?P<adr1>\S+?):(?P<port1>\S+)  # 1st address:port
                            \s+
                            (?P<adr2>\S+?):(?P<port2>\S+)  # 2nd address:port
                            \s+
                            (?P<adr>\S+?):(?P<port>\S+)    # proxy address:port
                            \s+
                            (?P<bytes1>\d+)                # bytes from peer1
                            /
                            (?P<bytes2>\d+)                # bytes from peer2
                            /
                            (?P<bytes>\d+)                 # bytes relayed
                            \s+
                            (?P<status>\S+)                # status
                            \s+
                            (?P<rtpCodec>\S+)              # RTP codec type
                            \s+
                            (?P<streamType>\S+)            # RTP stream type (audio/video)
                            \s+
                            (?P<idle>\d+)                  # idle time
                            ''', re.VERBOSE)


def normalizeBytes(bytes):
    mb = bytes/1024/1024.0
    kb = bytes/1024.0
    if mb >= 0.95:
        return "%.2fM" % mb
    elif kb >= 1:
        return "%.2fk" %kb
    else:
        return "%d" % bytes

def normalizeTraffic(traffic):
    mb = traffic/1024/1024.0
    kb = traffic/1024.0
    if mb >= 0.95:
        return "%.2fMbps" % mb
    elif kb >= 1:
        return "%.2fkbps" %kb
    else:
        return "%dbps" % traffic

def normalizeTime(period):
    min, sec = divmod(int(period), 60)
    h, min   = divmod(min, 60)
    if h >= 1:
        return '%dh%02d\'%02d"' % (h, min, sec)
    else:
        return '%d\'%02d"' % (min, sec)


if __name__ == '__main__':
    import socket
    import sys, errno
    import time
    from optparse import OptionParser
    from options import ExtendedOptions
    from formatting import Table
    from version import release

    ver = '%%prog %s' % release
    parser = OptionParser(option_class=ExtendedOptions, version=ver)
    parser.add_option("--proxy", dest="address", type="controlport",
                      default='/var/run/mediaproxy.sock',
                      help="mediaproxy's control port (/var/run/mediaproxy.sock)", 
                      metavar="Host|File")
    #parser.add_option("--active", action="store_true", dest="active", default=0,
    #                  help="show active connections only")
    (options, args) = parser.parse_args()
    if type(options.address) == type(()):
        type = socket.AF_INET
    else:
        type =  socket.AF_UNIX
    s = socket.socket(type, socket.SOCK_STREAM)
    try:
        s.connect(options.address)
    except socket.error, why:
        if why[0] == errno.ENOENT:
            print >>sys.stderr, "RTP Proxy's control socket doesn't exist (%s)" % options.address
        else:
            print >>sys.stderr, "Cannot connect to RTP Proxy's control socket: %s" % str(why[1])
        sys.exit(1)
    try:
        s.send('status\n')
        result = ''
        while 1:
            try:
                data = s.recv(1024)
                if not data:
                    break
                result += data
            except socket.error, why:
                print >>sys.stderr, "Cannot read result from MediaProxy: %s" % str(why[1])
                sys.exit(1)
    finally:
        s.close()

    header = ['Caller', '', 'Via', '', 'Called', '', 'Status', 'Duration', 'Codec', 'Type',
              'Traffic']
    output = Table(header)
    output.header.bodySeparator = '-'
    output.header.separators = [' ', '   ', ' ', '   ', ' ', '  ', '  ', '  ', '  ', '  ', '']
    output.separators =        [':', ' - ', ':', ' - ', ':', '  ', '  ', '  ', '  ', '  ', '']
    output.alignments = ['right', 'left', 'right', 'left', 'right', 'left', 'left',
                         'right', 'left', 'left', 'left']

    traffic = {'in1': 0, 'in2': 0, 'out': 0}
    
    lines = result.strip().splitlines()
    
    m = versionLine.search(lines[0].strip())
    if not m:
        version = 'unknown'
        idx = 0
    else:
        version = m.group('version')
        idx = 1
    m = summaryLine.search(lines[idx].strip())
    if not m:
        print >>sys.stderr, "Invalid summary line: %s" % lines[0].strip()
        sys.exit(1)

    sessionCount = int(m.group('sessions'))
    traffic1 = float(m.group('traffic1'))
    traffic2 = float(m.group('traffic2'))
    trafficr = float(m.group('traffic'))

    sessions = {}
    crtSession = None
    
    for l in lines[idx+1:]:
        line = l.strip()
        m = sessionLine.match(line)
        if m:
            crtSession = m.group('id')
            info = m.groupdict()
            info['streams'] = []
            sessions[crtSession] = info
            continue
        m = streamLine.search(line)
        if m:
            idle = int(float(m.group('idle')))
            status = m.group('status')
            if status in ('idle', 'hold'):
                status += ' (%02d)' % idle
            bytes  = long(m.group('bytes'))
            bytes1 = long(m.group('bytes1'))
            bytes2 = long(m.group('bytes2'))
            nbytes = "%s/%s/%s" % (normalizeBytes(bytes1), normalizeBytes(bytes),
                                   normalizeBytes(bytes2))
            session = [m.group('adr1'), m.group('port1'),
                       m.group('adr'),  m.group('port'),
                       m.group('adr2'), m.group('port2'),
                       status, normalizeTime(sessions[crtSession]['duration']),
                       m.group('rtpCodec'), m.group('streamType'), 
                       nbytes]
            output.append(session)
        else:
            print >>sys.stderr, "Invalid response line: %s" % line

    if not output:
        print 'No RTP sessions'
        sys.exit(0)

    print ''
    output.show()
    print ''
    print 'Total traffic:  %s/%s/%s (in1/in2/out)' % \
          (normalizeTraffic(traffic1*8),
           normalizeTraffic(traffic2*8),
           normalizeTraffic(trafficr*8))
    #print ''
    print 'Session count:  %s' % sessionCount
    #print 'Stream count:   %s' % count
    print 'Proxy version:  %s' % version
    print ''

