moving proxy files to pyogp/apps/proxy
This commit is contained in:
committed by
Salad Dais
parent
b0781d3fb0
commit
1fabf32d49
@@ -1,213 +0,0 @@
|
||||
|
||||
"""
|
||||
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
|
||||
from logging import getLogger
|
||||
from webob import Request, Response
|
||||
|
||||
# related
|
||||
from indra.base import llsd
|
||||
from eventlet import util
|
||||
|
||||
# the following makes socket calls nonblocking. magic
|
||||
util.wrap_socket_with_coroutine_socket()
|
||||
|
||||
# pyogp
|
||||
from pyogp.lib.base.datatypes import UUID
|
||||
from pyogp.lib.base.event_queue import EventQueueClient
|
||||
from pyogp.lib.base.exc import DataParsingError, HTTPError
|
||||
|
||||
# initialize logging
|
||||
logger = getLogger('pyogp.lib.base.caps_proxy')
|
||||
|
||||
class CapabilitiesProxy(object):
|
||||
""" an application class for wsgiref.simple_server which handles
|
||||
proxyied http requests and responses for capabilities """
|
||||
|
||||
def __init__(self,
|
||||
seed_cap_url,
|
||||
proxy_host_ip,
|
||||
proxy_host_port,
|
||||
message_handler = None,
|
||||
restclient = None):
|
||||
|
||||
# populated initially via the login response
|
||||
self.seed_cap_url = seed_cap_url
|
||||
|
||||
# the local proxy info, needed for building urls to send to the viewer
|
||||
self.proxy_host_ip = proxy_host_ip
|
||||
self.proxy_host_port = proxy_host_port
|
||||
|
||||
# allow the message handler to be passed in
|
||||
# otherwise, just set one up
|
||||
if message_handler != None:
|
||||
self.message_handler = message_handler
|
||||
else:
|
||||
from pyogp.lib.base.message.message_handler import MessageHandler
|
||||
self.message_handler = MessageHandler()
|
||||
|
||||
# we may in the future use something other than urllib2 (StdLibClient)
|
||||
if restclient == None:
|
||||
from pyogp.lib.base.network.stdlib_client import StdLibClient
|
||||
self.restclient = StdLibClient()
|
||||
else:
|
||||
self.restclient = restclient
|
||||
|
||||
# stores the capability url <-> proxy uuid combo
|
||||
self.proxy_map = {}
|
||||
|
||||
# stored the url:cap name map
|
||||
self.capability_map = {}
|
||||
|
||||
# stores the event_queue info for parsing special data
|
||||
self.event_queue_client = EventQueueClient()
|
||||
self.event_queue_url = None
|
||||
|
||||
# init the seed cap proxy
|
||||
self.add_proxy(self.seed_cap_url, 'seed_capability')
|
||||
|
||||
logger.info("Initialized the CapabilitiesProxy for %s" %
|
||||
(self.seed_cap_url))
|
||||
|
||||
def add_proxy(self, url, capname):
|
||||
""" adds the url and it's proxy, and the proxy and it's url"""
|
||||
|
||||
# make available UUID <-> url dicts
|
||||
# we map each since the pairs are unique
|
||||
# and since we need to do lookups both ways (?)
|
||||
try:
|
||||
test = self.proxy_map[url]
|
||||
except KeyError:
|
||||
uuid = str(UUID().random())
|
||||
self.proxy_map[url] = uuid
|
||||
self.proxy_map[uuid] = url
|
||||
|
||||
# store the url:capname
|
||||
self.capability_map[url] = capname
|
||||
|
||||
return uuid
|
||||
|
||||
def remove_proxy(self, proxied):
|
||||
""" removes the url and it's proxy, and the proxy and it's url"""
|
||||
|
||||
val = self.proxy_map[proxied]
|
||||
|
||||
try:
|
||||
del self.proxy_map[proxied]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
del self.proxy_map[val]
|
||||
del self.capability_map[val]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def swap_cap_urls(self, cap_map):
|
||||
""" takes the response to a seed_cap request for cap urls
|
||||
and maps proxy urls in place of the ones for the sim
|
||||
"""
|
||||
|
||||
# we expect a dict of {'capname':'url'}
|
||||
for cap in cap_map:
|
||||
|
||||
# store the EventQueueGet url separately
|
||||
if cap == 'EventQueueGet':
|
||||
self.event_queue_url = cap_map[cap]
|
||||
cap_proxy_uuid = self.add_proxy(cap_map[cap], cap)
|
||||
cap_map[cap] = "http://%s:%s/%s" % (self.proxy_host_ip,
|
||||
self.proxy_host_port,
|
||||
cap_proxy_uuid)
|
||||
|
||||
# store the url:capname
|
||||
self.capability_map[cap_map[cap]] = cap
|
||||
|
||||
return cap_map
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
""" handle a specific cap request and response using webob objects"""
|
||||
|
||||
self.environ = environ
|
||||
self.start = start_response
|
||||
self.request = Request(environ)
|
||||
self.response = Response()
|
||||
|
||||
logger.info("Calling cap %s (%s) via %s with body of: %s" %
|
||||
(self.capability_map[self.proxy_map[self.request.path[1:]]],
|
||||
self.proxy_map[self.request.path[1:]],
|
||||
self.request.method,
|
||||
self.request.body))
|
||||
|
||||
# urllib2 will return normally if the reponse status = 200
|
||||
# returns HTTPError if not
|
||||
# trap and send back to the viewer in either case
|
||||
try:
|
||||
|
||||
if self.request.method=="GET":
|
||||
|
||||
proxy_response = self.restclient.GET(self.proxy_map[self.request.path[1:]])
|
||||
|
||||
elif self.request.method == "POST":
|
||||
|
||||
proxy_response = self.restclient.POST(self.proxy_map[self.request.path[1:]],
|
||||
self.request.body)
|
||||
|
||||
logger.info("Cap %s (%s) responded with status %s and body of: %s" %
|
||||
(self.capability_map[self.proxy_map[self.request.path[1:]]],
|
||||
self.proxy_map[self.request.path[1:]],
|
||||
proxy_response.status,
|
||||
proxy_response.body))
|
||||
|
||||
# build the webob.Response to send to the viewer
|
||||
status = proxy_response.status
|
||||
|
||||
# if we are parsing the seed cap response, swap the cap urls
|
||||
# with our proxied ones
|
||||
if self.proxy_map[self.request.path[1:]] == self.seed_cap_url:
|
||||
|
||||
cap_map = self.swap_cap_urls(llsd.parse(proxy_response.body))
|
||||
data = llsd.format_xml(cap_map)
|
||||
|
||||
# if we are parsing the event queue, decode the data
|
||||
# then curry it on out
|
||||
elif self.proxy_map[self.request.path[1:]] == self.event_queue_url:
|
||||
|
||||
self.event_queue_client._parse_result(llsd.parse(proxy_response.body))
|
||||
data = proxy_response.body
|
||||
|
||||
# otherwise, just proxy the data
|
||||
else:
|
||||
|
||||
data = proxy_response.body
|
||||
|
||||
# trap the HTTPError and build the appropriate response for the caller
|
||||
except HTTPError, error:
|
||||
status = error.code
|
||||
data = error.msg
|
||||
|
||||
return self.send_response(status, data)
|
||||
|
||||
|
||||
def send_response(self, status, body=''):
|
||||
""" send the response back to the caller """
|
||||
|
||||
logger.debug("Sending cap response to viewer: Status:%s Body:%s" % (status, body))
|
||||
|
||||
self.response.status = status
|
||||
self.response.body = body
|
||||
return self.response(self.environ, self.start)
|
||||
@@ -1,137 +0,0 @@
|
||||
"""
|
||||
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)
|
||||
Reference in New Issue
Block a user