137 lines
5.3 KiB
Python
137 lines
5.3 KiB
Python
"""
|
|
Contributors can be viewed at:
|
|
http://svn.secondlife.com/svn/linden/projects/2008/pyogp/lib/base/trunk/CONTRIBUTORS.txt
|
|
|
|
$LicenseInfo:firstyear=2008&license=apachev2$
|
|
|
|
Copyright 2009, Linden Research, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0.
|
|
You may obtain a copy of the License at:
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
or in
|
|
http://svn.secondlife.com/svn/linden/projects/2008/pyogp/lib/base/LICENSE.txt
|
|
|
|
$/LicenseInfo$
|
|
"""
|
|
# standard python libs
|
|
from logging import getLogger
|
|
import socket
|
|
import traceback
|
|
|
|
# related
|
|
from eventlet import api
|
|
|
|
# pyogp
|
|
from pyogp.lib.base.message.circuit import Host
|
|
from pyogp.lib.base.message.udpdispatcher import UDPDispatcher
|
|
from pyogp.lib.base.network.net import NetUDPClient
|
|
|
|
# initialize logging
|
|
logger = getLogger('message.udpproxy')
|
|
|
|
class UDPProxy(UDPDispatcher):
|
|
""" proxies a Second Life viewer's UDP connection to a region """
|
|
|
|
def __init__(self, sim_ip, sim_port, viewer_facing_port, target_facing_port, udp_client = None, settings = None, message_handler = None, message_template = None, message_xml = None):
|
|
""" initialize a UDP proxy, extending the UDPDispatcher """
|
|
|
|
super(UDPProxy, self).__init__(udp_client, settings, message_handler, message_template, message_xml)
|
|
|
|
self.settings.PROXY_LOGGING = True
|
|
self.settings.ENABLE_DEFERRED_PACKET_PARSING = False # ToDo: remove this
|
|
|
|
self.target_host = Host((sim_ip, sim_port))
|
|
self.local_host = None
|
|
self.viewer_address = None
|
|
|
|
self.target_udp_client = self.udp_client # region facing
|
|
self.target_socket = self.socket # already spun up as part of the parent UDPDispatcher class instance
|
|
self.target_socket.bind((socket.gethostname(), target_facing_port)) # bind it to a port
|
|
self.target_socket.setblocking(0) # set the socket to nonblocking
|
|
|
|
self.proxy_udp_client = NetUDPClient() # the viewer's socket
|
|
self.proxy_socket = self.proxy_udp_client.start_udp_connection() # grab a socket!
|
|
self.proxy_socket.bind((socket.gethostname(), viewer_facing_port)) # bind it to a port
|
|
self.proxy_socket.setblocking(0) # set the socket to nonblocking
|
|
|
|
# the viewer needs a local hostname to connect to, as well as a port
|
|
self.hostname = self.proxy_socket.getsockname()[0]
|
|
|
|
self.local_host = Host((self.hostname, viewer_facing_port)) # populate this convenience reference
|
|
|
|
#logger.debug("Bound proxy for region %s to %s" % (self.target_host, self.target_socket.getsockname()))
|
|
#logger.debug("Bound proxy for viewer (%s) to %s" % (self.local_host, self.proxy_socket.getsockname()))
|
|
logger.info("Initialized the UDPProxy for %s" % (self.target_host))
|
|
|
|
def start_proxy(self):
|
|
|
|
logger.debug("Starting proxies in UDPProxy")
|
|
|
|
api.sleep(2)
|
|
|
|
self._is_running = True
|
|
|
|
api.spawn(self._send_viewer_to_sim)
|
|
api.spawn(self._receive_sim_to_viewer)
|
|
|
|
while self._is_running:
|
|
|
|
api.sleep(0)
|
|
|
|
|
|
def _send_viewer_to_sim(self):
|
|
|
|
# todo: find a way to not try and send data we just received
|
|
self.proxy_socket_is_locked = False
|
|
|
|
while self._is_running:
|
|
|
|
msg_buf, msg_size = self.proxy_udp_client.receive_packet(self.proxy_socket)
|
|
|
|
if not self.viewer_address:
|
|
self.viewer_address = self.proxy_udp_client.get_sender()
|
|
|
|
if msg_size > 0:
|
|
try:
|
|
recv_packet = self.receive_check(self.proxy_udp_client.get_sender(),
|
|
msg_buf,
|
|
msg_size)
|
|
|
|
logger.info("Sending message:%s ID:%s" % (recv_packet.name, recv_packet.packet_id))
|
|
logger.debug(recv_packet) # ToDo: make this optionally llsd logging once that's in
|
|
except Exception, error:
|
|
logger.error("Problem handling viewer to sim proxy: %s." % (error))
|
|
traceback.print_exc()
|
|
|
|
self.target_udp_client.send_packet(self.target_socket,
|
|
msg_buf,
|
|
self.target_host)
|
|
|
|
|
|
api.sleep(0)
|
|
|
|
def _receive_sim_to_viewer(self):
|
|
|
|
while self._is_running:
|
|
|
|
msg_buf, msg_size = self.target_udp_client.receive_packet(self.target_socket)
|
|
|
|
if msg_size > 0:
|
|
try:
|
|
recv_packet = self.receive_check(self.target_udp_client.get_sender(),
|
|
msg_buf,
|
|
msg_size)
|
|
|
|
logger.info("Receiving message:%s ID:%s" % (recv_packet.name, recv_packet.packet_id))
|
|
logger.debug(recv_packet) # ToDo: make this optionally llsd logging once that's in
|
|
except Exception, error:
|
|
logger.warning("Problem trying to handle sim to viewer proxy : %s" % (error))
|
|
traceback.print_exc()
|
|
|
|
self.proxy_udp_client.send_packet(self.proxy_socket,
|
|
msg_buf,
|
|
self.viewer_address)
|
|
|
|
|
|
api.sleep(0) |