Files
Hippolyzer/pyogp/lib/base/message_manager.py

197 lines
6.7 KiB
Python

"""
message_manager.py
Implements the MessageManager class which faciliates the sending and receiving
of messages between a simulator through either the UDP or Capability message
paths.
Contributors: http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt
$LicenseInfo:firstyear=2008&license=apachev2$
Copyright (c) 2009, Linden Research, Inc.
Licensed under the Apache License, Version 2.0 (the "License").
You may obtain a copy of the License at:
http://svn.secondlife.com/svn/linden/projects/2008/pyogp/LICENSE.txt
$/LicenseInfo$
"""
#stdlib
from logging import getLogger
# pyogp.lib.base
from pyogp.lib.base.message.udpdispatcher import UDPDispatcher
from pyogp.lib.base.message.message_handler import MessageHandler
from pyogp.lib.base.message.message_dot_xml import MessageDotXML
from pyogp.lib.base.event_queue import EventQueueClient
from pyogp.lib.base.settings import Settings
# related
from eventlet import api
# initialize logging
logger = getLogger('pyogp.lib.base.message_manager')
class MessageManager(object):
"""
This object serves as a consolidation point for all messaging related
functionality in the base/message directory.
"""
def __init__(self, host, message_handler=None, capabilities={},
settings=None, start_monitors=False, message_template = None, message_xml = None):
"""
Initialize the MessageManager, applying custom settings and dedicated
message_handler if needed
"""
logger.debug("Initializing the Message Manager ")
self.host = host
# allow the settings to be passed in
# otherwise, grab the defaults
if settings != None:
self.settings = settings
else:
self.settings = Settings()
# allow the message_handler to be passed in
# otherwise, grab the defaults
if message_handler != None:
self.message_handler = message_handler
elif self.settings.HANDLE_PACKETS:
self.message_handler = MessageHandler()
# allow the passing in of message_template.msg as a file handle
if not message_template:
self.message_template = None
else:
if isinstance(message_template, file):
self.message_template = message_template
else:
log.warning("%s parameter is expected to be a filehandle, it is a %s. \
Using the embedded message_template.msg" % (message_template, type(message_template)))
from pyogp.lib.base.data import msg_tmpl
self.message_template = msg_tmpl
# allow the passing in of message.xml as a file handle
# mapped to MessageDotXML()
if not message_xml:
self.message_xml = MessageDotXML()
else:
if isinstance(message_xml, file):
self.message_xml = MessageDotXML(message_xml = message_xml.read())
else:
log.warning("%s parameter is expected to be a filehandle, it is a %s. \
Using the embedded message.xml" % (message_xml, type(message_xml)))
self.message_xml = MessageDotXML()
# initialize the manager's base attributes
#self.builder = MessageBuilder()
self._is_running = False
#event queue-related attributes
self.capabilities = capabilities
if self.capabilities.has_key('EventQueueGet'):
self.event_queue = EventQueueClient(self.capabilities['EventQueueGet'],
message_handler = self.message_handler,
host = self.host)
else:
self.event_queue = None
#UDP-related attributes
#NOTE udpdispatcher can already multiplex hosts
self.incoming_queue = []
self.outgoing_queue = []
self.udp_dispatcher = UDPDispatcher(settings = self.settings,
message_handler = self.message_handler,
message_template = self.message_template)
# if start parameter = True, kick off the queue monitors
if start_monitors:
self.start_monitors()
def start_monitors(self):
""" spawn queue monitoring coroutines """
self._is_running = True
logger.debug('Spawning region UDP connection')
api.spawn(self._udp_dispatcher)
if self.event_queue != None:
logger.debug('Spawning region event queue connection')
api.spawn(self.event_queue.start)
#api.spawn(self.monitor_outgoing_queue)
#api.spawn(self.monitor_incoming_queue)
def stop_monitors(self):
""" stops monitoring coroutines """
#stops udp_dispatcher
self._is_running = False
#stops event_queue
if self.event_queue._running:
self.event_queue.stop()
def monitor_outgoing_queue(self):
""" """
pass
def enqueue_message(self, message, reliable = False,
now = False):
""" enqueues a Message() in the outgoing_queue """
# ToDo: should a reliable flag parameter be required here?
if now:
self.outgoing_queue.insert(0, (message, reliable))
else:
self.outgoing_queue.append((message, reliable))
def send_message(self):
""" """
pass
def new_message(self, name):
pass
def _udp_dispatcher(self):
"""
Sends and receives UDP messages.
"""
logger.debug('Spawning region UDP connection')
while self._is_running:
api.sleep(0)
msg_buf, msg_size = self.udp_dispatcher.udp_client.receive_packet(self.udp_dispatcher.socket)
recv_packet = self.udp_dispatcher.receive_check(self.udp_dispatcher.udp_client.get_sender(),
msg_buf,
msg_size)
#self.incoming_queue.append(recv_packet)
if self.udp_dispatcher.has_unacked():
self.udp_dispatcher.process_acks()
while len(self.outgoing_queue) > 0:
(packet, reliable) = self.outgoing_queue.pop(0)
self.send_udp_message(packet, reliable)
logger.debug("Stopped the UDP connection for %s" % (self.host))
def send_udp_message(self, packet, reliable=False):
"""
Immediately sends an udp message to host
"""
if reliable:
return self.udp_dispatcher.send_reliable(packet, self.host, 0)
else:
return self.udp_dispatcher.send_message(packet, self.host)