Go to the documentation of this file.00001
00002 import roslib
00003 roslib.load_manifest('roswww')
00004 import rospy
00005
00006 import socket
00007 import subprocess
00008
00009 import tornado.ioloop
00010 import tornado.web
00011
00012 def run(*args):
00013 '''run the provided command and return its stdout'''
00014 args = sum([(arg if type(arg) == list else [arg]) for arg in args], [])
00015 return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].strip()
00016
00017 def split_words(text):
00018 '''return a list of lines where each line is a list of words'''
00019 return [line.strip().split() for line in text.split('\n')]
00020
00021 def get_packages():
00022 ''' Find the names and locations of all packages '''
00023 lines = split_words(run('rospack', 'list'))
00024 packages = [{ 'name': name, 'path': path } for name, path in lines]
00025 return packages
00026
00027 class MainHandler(tornado.web.RequestHandler):
00028
00029 def initialize(self, packages):
00030 self.packages = packages
00031
00032 def get(self):
00033 self.write("<h1>ROS web server successfully started.</h1><h3>Package List</h3>")
00034 for package in self.packages:
00035 self.write("<div style='font-size: 10px'>"+package['name']+"</div>")
00036
00037 def create_webserver(packages):
00038 handlers = [(r"/", MainHandler, {"packages": packages})]
00039
00040 for package in packages:
00041 handler = ("/"+package['name']+"/(.*)", tornado.web.StaticFileHandler, {"path": package['path']+"/www", "default_filename": "index.html" })
00042 handlers.append(handler)
00043
00044 rospy.loginfo("Webserver initialized for %d packages", len(packages))
00045 application = tornado.web.Application(handlers)
00046
00047 return application
00048
00049 def bind_webserver(application):
00050 """ See if there's a default port, use 80 if not """
00051 default_port, start_port, end_port = get_webserver_params()
00052
00053 """ First, we try the default http port 80 """
00054 bound = bind_to_port(application, default_port)
00055
00056 if not bound:
00057 """ Otherwise bind any available port within the specified range """
00058 bound = bind_in_range(application, start_port, end_port)
00059
00060 return bound
00061
00062 def get_webserver_params():
00063 try:
00064 default_port = rospy.get_param("http/default", 80)
00065 start_port = rospy.get_param("http/range_start", 8000)
00066 end_port = rospy.get_param("http/range_end", 9000)
00067 return (default_port, start_port, end_port)
00068 except socket.error as err:
00069 if err.errno == 111:
00070
00071 rospy.logwarn("Could not contact ROS master. Is a roscore running? Error: %s", err.strerror)
00072 return 80, 8000, 9000
00073 else:
00074 raise
00075
00076 def start_webserver(application):
00077 try:
00078 tornado.ioloop.IOLoop.instance().start()
00079 except KeyboardInterrupt:
00080 rospy.loginfo("Webserver shutting down")
00081
00082 def bind_to_port(application, portno):
00083 rospy.loginfo("Attempting to start webserver on port %d", portno)
00084 try:
00085 application.listen(portno)
00086 rospy.loginfo("Webserver successfully started on port %d", portno)
00087 except socket.error as err:
00088
00089 if err.errno==13:
00090 rospy.logwarn("Insufficient priveliges to run webserver on port %d. Error: %s", portno, err.strerror)
00091 rospy.loginfo("-- Try re-running as super-user: sudo su; source ~/.bashrc)")
00092 elif err.errno==98:
00093 rospy.logwarn("There is already a webserver running on port %d. Error: %s", portno, err.strerror)
00094 rospy.loginfo("-- Try stopping your web server. For example, to stop apache: sudo /etc/init.d/apache2 stop")
00095 else:
00096 rospy.logerr("An error occurred attempting to listen on port %d: %s", portno, err.strerror)
00097 return False
00098 return True
00099
00100 def bind_in_range(application, start_port, end_port):
00101 if (end_port > start_port):
00102 for i in range(start_port, end_port):
00103 if bind_to_port(application, i):
00104 return True
00105 return False
00106
00107 def run_webserver():
00108 try:
00109 packages = get_packages()
00110 server = create_webserver(packages)
00111 bound = bind_webserver(server)
00112 if (bound):
00113 start_webserver(server)
00114 else:
00115 raise Exception()
00116 except Exception as exc:
00117 rospy.logerr("Unable to bind webserver. Exiting. %s" % exc)
00118
00119 if __name__=='__main__':
00120 run_webserver()