Skip to content

Commit

Permalink
Added Curmur controls scripts for EC_VoiceChannel usage
Browse files Browse the repository at this point in the history
  • Loading branch information
mattiku committed Nov 11, 2010
1 parent 613b5e9 commit 56b6d43
Show file tree
Hide file tree
Showing 5 changed files with 303 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import sys
import Ice
import Murmur_ice

class ChannelManager:
'''
All channels created by this script are marked by setting description field to 'EC_VoiceChannel'
By calling 'remove_channel' onl subchannels marked as 'EC_VoiceChannel' are removed
@todo: Channel name validator
'''
ROOT_ID = -1
def __init__(self, address, port):
ic = Ice.initialize(sys.argv)
base = ic.stringToProxy("Meta:tcp -h "+str(address)+" -p "+str(port))
meta_proxy = Murmur_ice._M_Murmur.MetaPrx.checkedCast(base)
list = meta_proxy.getBootedServers()
self._server_proxy = list[0]

def get_or_create_channel(self, full_name):
channel = self._get_channel_by_full_name(full_name)
if channel is None:
self._create_channel(full_name)

def remove_channel(self, full_name):
names = full_name.split('/')
for depth in range(0,len(names)):
name = names[depth]
sub_channel_name = ""
for i in range(0, len(names) - depth):
if i == 0:
sub_channel_name = names[i]
else:
sub_channel_name = sub_channel_name + '/'+ names[i]
channel = self._get_channel_by_full_name(sub_channel_name)
if channel is not None and channel.description == "EC_VoiceChannel" and len(self._get_children(channel)) == 0:
self._server_proxy.removeChannel(channel.id)

def _get_children(self, channel):
children = []
channels = self._server_proxy.getChannels().values()
for c in channels:
if c.parent == channel.id:
children.append(c)
return children


def _get_channel_by_full_name(self, full_name):
'''
return a channel with parent channels descriped by given 'full_name'
'''
names = full_name.split('/')
tree = self._server_proxy.getTree()
root = tree.c
children = tree.children
channel = None
for depth in range(0,len(names)):
name = names[depth]
channel = None
for child in children:
if child.c.name == name:
channel = child.c
break
if channel is None:
return None
children = child.children
return channel

def _create_channel(self, full_name):
''' Created all necessary channels
eg. "channelA/ChannelB" -> channelA, channelB
'''
names = full_name.split('/')
tree = self._server_proxy.getTree()
root = tree.c
children = tree.children
next_parent_id = tree.c.id
for depth in range(0,len(names)):
name = names[depth]
channel = None
for child in children:
if child.c.name == name:
channel = child.c
next_parent_id = channel.id
break
if channel is None:
id = self._server_proxy.addChannel(name, next_parent_id)
new_channel = self._server_proxy.getChannels()[id]
if new_channel is not None:
new_channel.temporary = True # DOESN'T WORK!
new_channel.description = "EC_VoiceChannel"
self._server_proxy.setChannelState(new_channel)
if depth < len(names)-1:
self._create_channel(full_name) # recursive call !
return
children = child.children
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import sys, time
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from MumbleChannelManager import ChannelManager

'''
Makes possible to add and delete Murmur channels using http requests.
request format: <server host:port>/<secret>/CREATE_CHANNEL/<channel name>
<server host:port>/<secret>/REMOVE_CHANNEL/<channel name>
Idea of the secret is that only scripts which know the <Secret> are able to
create or delete the channels
'''

SERVER_HOST_NAME = ''
SERVER_PORT_NUMBER = 9999

SECRET = "qwerty123" # REMEMBER TO CHANGE THIS !!!

MURMUR_HOST_NAME = "127.0.0.1"
MURMUR_PORT_NUMBER = 6502

class RequestHandler(BaseHTTPRequestHandler):

def do_GET(self):
from_address, from_port = self.client_address
if self._is_remove_request() and self._is_secret_ok():
full_name = self._get_full_channel_name()
if full_name is not None:
print(time.asctime() + " Remove request from %s: %s" % (from_address, full_name))
self._channel_manager = ChannelManager(MURMUR_HOST_NAME, MURMUR_PORT_NUMBER)
self._channel_manager.remove_channel(full_name)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write("OK")
return

if self._is_create_request() and self._is_secret_ok():
full_name = self._get_full_channel_name()

if full_name is not None:
print(time.asctime() + " Create request from %s: %s" % (from_address, full_name))
self._channel_manager = ChannelManager(MURMUR_HOST_NAME, MURMUR_PORT_NUMBER)
self._channel_manager.get_or_create_channel(full_name)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write("OK")
return

print(time.asctime() + " Bad request from %s: %s" % (from_address, self.path))
self.send_response(404)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write("FAIL")

def _is_secret_ok(self):
'''return True if the <secret> was corrent. Otherwise return false
@param s http request
'''
try:
secret = self.path.strip('/').split('/')[0]
if secret == SECRET:
return True
else:
return False
except:
return False

def _is_remove_request(self):
''' return True if the request was REMOVE_CHANNEL otherwise return False
@param s http request
'''
try:
command = self.path.strip('/').split('/')[1]
if command == "REMOVE_CHANNEL":
return True
else:
return False
except:
return False

def _is_create_request(self):
''' return True if the request was REMOVE_CHANNEL otherwise return False
@param s http request
'''
try:
command = self.path.strip('/').split('/')[1]
if command == "CREATE_CHANNEL":
return True
else:
return False
except:
return False

def _get_full_channel_name(self):
''' Return the full channel name in the request.
if channel name cannot parsed from the request then return None
'''
try:
parts = self.path.strip('/').split('/')
full_name = None
for i in range(2, len(parts)):
if full_name is None:
full_name = parts[i]
else:
full_name = full_name + "/" + parts[i]
return full_name
except:
return None

def log_message(format, *args):
''' to disable default log messages'''
return



class Service():

def __init__(self):
self._httpd = HTTPServer((SERVER_HOST_NAME, SERVER_PORT_NUMBER), RequestHandler)

def run(self):
try:
self._httpd.serve_forever()
except KeyboardInterrupt:
pass
self._httpd.server_close()

if __name__ == '__main__':
print ("To create and delete channels:")
print (" http://%s:%s/%s/CREATE_CHANNEL/MyChannel/MySubChannel" % (SERVER_HOST_NAME, SERVER_PORT_NUMBER, SECRET))
print (" http://%s:%s/%s/REMOVE_CHANNEL/MyChannel/MySubChannel" % (SERVER_HOST_NAME, SERVER_PORT_NUMBER, SECRET))
print ("")
print time.asctime(), "Service Starts - %s:%s" % (SERVER_HOST_NAME, SERVER_PORT_NUMBER)
print ("Press CRTL-C to quit service.")
service = Service()
service.run()
print time.asctime(), "Service Stops - %s:%s" % (SERVER_HOST_NAME, SERVER_PORT_NUMBER)

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
If you want to enabled automatic mumble channel management:

* run MurmurControlService.py script.
- this must be run at the same computer than murmur server is running
- This starts http server and creates and removes channels according requests from 'voicechannel.py' script.
* set rex property 'ServerScriptClass' to 'voicechannel' for the object having EC_VoiceChannel component

2 changes: 2 additions & 0 deletions bin/ScriptEngines/PythonScript/mumble/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
print "Initializing voicehannel"
import voicehannel
57 changes: 57 additions & 0 deletions bin/ScriptEngines/PythonScript/mumble/voicechannel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import urllib
import rxactor

'''
This script ensures that there is a mumble channel existing for the EC_VoiceChannel component.
When channelid attribute of EC_VoiceChannel component is changed the old channel is removed.
'''

SERVER_ADDRESS = "127.0.0.1:9999" # address of computer running MurmurControl/MurmurControlService.py
SECRET = "qwerty123" # REMEMBER TO CHANGE THIS !!! @see MurmurControl/MurmurControlService.py

CREATE_BASE_URL = "http://"+SERVER_ADDRESS+"/"+SECRET+"/CREATE_CHANNEL/" #todo get from ini
REMOVE_BASE_URL = "http://"+SERVER_ADDRESS+"/"+SECRET+"/REMOVE_CHANNEL/" #todo get from ini

class ChannelChecker(rxactor.Actor):
@staticmethod
def GetScriptClassName():
return "voicechannel.ChannelChecker"

def EventCreated(self):
self._cleanup_url = None
self.SetTimer(0.5, True) # We poll EC_VoiceChannel for channelid attribute
self.create_channel()
# @todo replace polling with proper event handlers
#rex_objects = self.MyWorld.CS.World.EventManager.OnClientConnect += self.clientConnectedHandle

def EventDestroyed(self):
self.cleanup()

def create_channel(self):
ec = self.rexGetECAttributes("EC_VoiceChannel")
if ec is not None:
cleanup_url = REMOVE_BASE_URL + str( ec["channelid"] )
if self._cleanup_url != cleanup_url:
url = CREATE_BASE_URL + str( ec["channelid"] )
urllib.urlopen(url)
self.cleanup()
self._cleanup_url = cleanup_url

def EventTimer(self):
self.create_channel()

def cleanup(self):
if self._cleanup_url is not None:
urllib.urlopen(self._cleanup_url)
self._cleanup_url = None

# @todo replace polling with proper event handlers
#def clientConnectedHandle(self, client_core):
# client_core.OnPrimFreeData += self.onPrimFreeData

#def onPrimFreeData(self, client, data):
# self.create_channel()



0 comments on commit 56b6d43

Please sign in to comment.