#!/usr/pkg/bin/python2.7
#----------------------------------------------------------------------------
# Project Name: MOSS
# File Name: moss.py
# Description: Run server.
#
# Created: 2004. 06. 20
# RCS-ID: $Id: moss.py,v 1.87 2004/10/23 11:22:42 myunggoni Exp $
# Copyright: (c) 2004 by myunggoni
# License: GNU General Public License
# Author: Myung-Gon Park <myunggoni@users.kldp.net>
#----------------------------------------------------------------------------

__package__ = "MOSS"
__version__ = "0.1.13"

import ConfigParser
import sys
import getopt
import os
import live
import web

try:
	import ogg.vorbis
	ogg_support = "yes"
except ImportError:
	ogg_support = "no"

try:
	import signal
	signal_support = "yes"
except ImportError:
	signal_support = "no"

def sigterm_handler(signum, frame):
	server.stop()
	
def sighup_handler(signum, frame):
	server.restart()
	
def daemonize(pidfile = None, stdin = "/dev/null", stdout = "/dev/null", stderr = "/dev/null"):
	try: 
		pid = os.fork() 
		if pid > 0:
			sys.exit(0) # Exit first parent.
	except OSError, error: 
		sys.stdout.write("Fork #1 failed: %s\n" % (error.strerror))
		sys.exit(1)
        
	os.chdir("/") 
	os.umask(0) 
	os.setsid() 
   
	try: 
		pid = os.fork() 
		if pid > 0:
			sys.exit(0) # Exit second parent.
	except OSError, error: 
		sys.stdout.write("Fork #2 failed: %s\n" % (error.strerror))
		sys.exit(1)

	pid = str(os.getpid())
	
	if pidfile:
		try:
			file(pidfile, "w+").write("%s\n" % pid)
		except IOError, error:
			sys.stdout.write("Invalid pidfile: %s\n" % (error.strerror))
			sys.exit(1)
	
	si = open(stdin, "r")
	so = open(stdout, "a+")
	se = open(stderr, "a+", 0)
	
	os.dup2(si.fileno(), sys.stdin.fileno())
	os.dup2(so.fileno(), sys.stdout.fileno())
	os.dup2(se.fileno(), sys.stderr.fileno())

class MOSS:
	def __init__(self, config_file, server_mode):
		self.running = False
		self.reconfig = False
		self.config_file = config_file
		self.server_mode = server_mode

		
		if server_mode == "web":
			self.server = web.Server(config_file)
		else:
			self.server = live.Server(config_file)

		if signal_support == "yes":
			if "SIGTERM" in dir(signal):
				signal.signal(signal.SIGTERM, sigterm_handler)
			if "SIGHUP" in dir(signal):
				signal.signal(signal.SIGHUP, sighup_handler)
		
	def run(self):
		self.running = True
		self.server.log_message("Server started with pid %d" % os.getpid())

		if self.server_mode == "web":									
			try:
				while self.running:
					if self.reconfig:
						self.server.log_message("Reloading configuraion file")
						self.server.server_close()
						self.server = web.Server(self.config_file)
						self.reconfig = False

					self.server.handle_request()

				self.server.log_message("Now taking down the server...")
			
			except KeyboardInterrupt:
				self.stop()
				self.server.log_message("KeyboardInterrupt occured")
				self.server.log_message("Please wait while the remaining streams finish...")
			except:
				self.stop()
				self.server.log_message("Please wait while the remaining streams finish...")
			
		else:
			try:
				while self.running:
					if self.reconfig:
						self.server.log_message("Reloading configuration file")
						self.server.server_close()
						self.server = live.Server(self.config_file)
						self.reconfig = False

					self.server.serve_forever()
			
				self.server.log_message("Now taking down the server...")
			
			except KeyboardInterrupt:
				self.stop()
				self.server.log_message("KeyboardInterrupt occured")
			except:
				self.stop()
				self.server.log_message("Please wait while the remaining streams finish...")

	def stop(self):
		self.running = False
		self.server.server_close()

	def restart(self):
		self.reconfig = True
		self.server.server_close()

	def IsRunning(self):
		return self.running		

def print_usage():
	print "Usage: %s [-d] [-n] [-c <filename>]" % os.path.basename(sys.argv[0])
	print "       -h     --help         Display this usage information"
	print "       -d     --debug-mode   Run as a debug mode"
	print "       -n     --no-pidfile   Do not generate pidfile (Automatically activated when server run as a debug mode)"
	print "       -c     --config-file  Specify the config file (default: %s)" % os.path.join(sys.prefix, "etc/moss.conf")

def main():
	try:
		opts, args = getopt.getopt(sys.argv[1:], "hdnc:", ["help", "debug-mode", "no-pidfile", "config-file"])
	except getopt.GetoptError:
		print_usage()
		sys.exit(1)

	global server
	debug_mode = False
	no_pidfile = False
	config_file = os.path.join(sys.prefix, "etc/moss.conf")

	for opt, arg in opts:
		if opt in ("-h", "--help"):
			print_usage()
			sys.exit(0)
		
		if opt in ("-d", "--debug-mode"):
			debug_mode = True
		
		if opt in ("-n", "--no-pidfile"):
			no_pidfile = True

		if opt in ("-c", "--config-file"):
			config_file = arg
			
			if not os.path.isfile(config_file):
				print "No such configuration file"
				print_usage()
				sys.exit(1)

	if os.path.isfile(config_file):
		config = ConfigParser.ConfigParser()
		config_defaults = config.defaults()
		config_defaults["server-mode"] = "web"
		config_defaults["pidfile"] = "/tmp/moss.pid"
		config.read(config_file)
		server_mode = config.get("server", "server-mode")
		pidfile = config.get("server", "pidfile")
	
		if server_mode in ("web", "live"):
			web.debug_mode = debug_mode
			live.debug_mode = debug_mode
		else:
			print "Invalid server mode"
			sys.exit(1)
			
	else:
		print "Configuration file not found"
		sys.exit(1)

	if not debug_mode:
		config_file = os.path.realpath(config_file)
		
		if no_pidfile:
			pidfile = None
		else:
			pidfile = os.path.realpath(pidfile)

		daemonize(pidfile)
	else:
		print "Entering in %s mode" % server_mode

		if ogg_support == "yes":
			print "Ogg vorbis support enabled"
		else:
			print "Ogg vorbis support disabled"
			print "To enable it you will need to install the 'pyogg' and the 'pyvorbis' modules"

	server = MOSS(config_file, server_mode)
	server.run()
			
if __name__ == "__main__":
	main()
