197 lines
6.7 KiB
Python
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)
|
|
|