#!/usr/bin/env python

'''Provides a RTP Proxy server to be used in conjunction with SER's mediaproxy
module. MediaProxy stands in between the 2 SIP clients participating in a VoIP
conversation and forwards the RTP and RTCP streams between them, allowing
the SIP clients to work behind NAT without special settings on their behalf.
MediaProxy must have a public IP.

Copyright 2003-2005 Dan Pascu
'''

## 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

if __name__ == '__main__':
    import daemon
    import sys, re
    from optparse import OptionParser
    from options import ExtendedOptions
    from configuration import getOption, Boolean
    from utilities import thisHostIP
    from datatypes import IPAddress
    from version import release

    ver = '%%prog %s' % release
    parser = OptionParser(option_class=ExtendedOptions, version=ver)
    parser.add_option("--no-fork", action="store_false", dest="fork", default=1,
                      help="run the process in the foreground")
    parser.add_option("--pid", dest="pidFile", default='/var/run/mediaproxy.pid',
                      help="pid file (/var/run/mediaproxy.pid)", 
                      metavar="File")
    parser.add_option("--log", dest="logFile", default=None,
                      help="log to this file too, along with syslog (None)",
                      metavar="File")
    #parser.add_option("--profile", action="store_true", dest="profile", default=0,
                      #help="profile function calls (don't use in production!)")
    (options, args) = parser.parse_args()

    #if options.profile:
        #import psyco
        ##psyco.log()
        ##psyco.profile()
        #psyco.full()

    ## Pass the command line options (or the default values) to the rtphandler module

    proxyIP = getOption('MediaProxy', 'proxyIP', thisHostIP, IPAddress)
    if not proxyIP:
        print "Cannot determine the IP address of this host!"
        print "Please specify one in the configuration file."
        sys.exit(1)

    if options.fork:
        try:
            d = daemon.Daemon('mediaproxy', options.pidFile, logFile=options.logFile, useSyslog=1)
        except daemon.DaemonError, why:
            print >>sys.stderr, "Mediaproxy error: %s. Exiting." % why
            sys.exit(1)

    ## We test for this after we fork because we want the message to go to syslog if we fork
    shouldStart = getOption('MediaProxy', 'start', True, otype=Boolean)
    if not shouldStart:
        print "disabled from configuration"
        sys.exit(0)

    ## Import rtphandler only after we fork, as it loads the accounting module which
    ## creates network connections, an extra thread and registers an atexit function.
    ## All these should only exist in the child to avoid troubles when the parent exits.
    import rtphandler
    proxyConfig = rtphandler.ProxyConfig

    try:
        ## Start local command handler if enabled
        handler = None
        if proxyConfig.socket:
            handler = rtphandler.ControlSocket()
        where = handler and ("`%s'" % proxyConfig.socket) or "is disabled"
        print "Listening for commands on local socket %s" % where

        ## Start remote command handler if requested
        if proxyConfig.listen is not None:
            handler = rtphandler.RemoteControl()
            print "Listening for remote commands on `%s:%s'" % proxyConfig.listen
            where = handler.aclStr()
            if where == 'anywhere':
                where = "anywhere!!! beware!"
            print "Remote commands are allowed from: %s" % where
        else:
            print "Listening for remote commands is disabled"

        ## Print some more startup info
        if handler:
            print "Using IP address `%s' for the RTP/RTCP proxy" % proxyIP
        else:
            print "No control sockets defined! Cannot receive any command at all. Exiting."

        if proxyConfig.forceClose > 0:
            print "Sessions will be forcefully closed after %s seconds" % proxyConfig.forceClose

        ## Start main loop. Note that this will return immediately and exit if no control
        ## sockets are defined at all. this is why there is no sys.exit() above
        rtphandler.loop()

    except rtphandler.MediaProxyError, why:
        print >>sys.stderr, "Mediaproxy error: %s." % why
    except KeyboardInterrupt:
        print >>sys.stderr, "Got keyboard interrupt. Exiting."
    except daemon.DaemonQuit, msg:
        print >>sys.stderr, msg

    # ev call this
    #rtphandler.asyncore.close_all()

