tcp_handler.py
Go to the documentation of this file.
1 import rospy
2 import struct
3 from rosbridge_library.rosbridge_protocol import RosbridgeProtocol
4 
5 try:
6  import SocketServer
7 except ImportError:
8  import socketserver as SocketServer
9 
10 class RosbridgeTcpSocket(SocketServer.BaseRequestHandler):
11  """
12  TCP Socket server for rosbridge
13  """
14 
15  busy = False
16  queue = []
17  client_id_seed = 0
18  clients_connected = 0
19  client_count_pub = None
20 
21  # list of parameters
22  incoming_buffer = 65536 # bytes
23  socket_timeout = 10 # seconds
24  # The following are passed on to RosbridgeProtocol
25  # defragmentation.py:
26  fragment_timeout = 600 # seconds
27  # protocol.py:
28  delay_between_messages = 0 # seconds
29  max_message_size = None # bytes
30  unregister_timeout = 10.0 # seconds
31  bson_only_mode = False
32 
33  def setup(self):
34  cls = self.__class__
35  parameters = {
36  "fragment_timeout": cls.fragment_timeout,
37  "delay_between_messages": cls.delay_between_messages,
38  "max_message_size": cls.max_message_size,
39  "unregister_timeout": cls.unregister_timeout,
40  "bson_only_mode": cls.bson_only_mode
41  }
42 
43  try:
44  self.protocol = RosbridgeProtocol(cls.client_id_seed, parameters=parameters)
45  self.protocol.outgoing = self.send_message
46  cls.client_id_seed += 1
47  cls.clients_connected += 1
48  if cls.client_count_pub:
49  cls.client_count_pub.publish(cls.clients_connected)
50  self.protocol.log("info", "connected. " + str(cls.clients_connected) + " client total.")
51  except Exception as exc:
52  rospy.logerr("Unable to accept incoming connection. Reason: %s", str(exc))
53 
54  def recvall(self,n):
55  # http://stackoverflow.com/questions/17667903/python-socket-receive-large-amount-of-data
56  # Helper function to recv n bytes or return None if EOF is hit
57  data = ''
58  while len(data) < n:
59  packet = self.request.recv(n - len(data))
60  if not packet:
61  return None
62  data += packet
63  return data
64 
65  def recv_bson(self):
66  # Read 4 bytes to get the length of the BSON packet
67  BSON_LENGTH_IN_BYTES = 4
68  raw_msglen = self.recvall(BSON_LENGTH_IN_BYTES)
69  if not raw_msglen:
70  return None
71  msglen = struct.unpack('i', raw_msglen)[0]
72 
73  # Retrieve the rest of the message
74  data = self.recvall(msglen - BSON_LENGTH_IN_BYTES)
75  if data == None:
76  return None
77  data = raw_msglen + data # Prefix the data with the message length that has already been received.
78  # The message length is part of BSONs message format
79 
80  # Exit on empty message
81  if len(data) == 0:
82  return None
83 
84  self.protocol.incoming(data)
85  return True
86 
87  def handle(self):
88  """
89  Listen for TCP messages
90  """
91  cls = self.__class__
92  self.request.settimeout(cls.socket_timeout)
93  while 1:
94  try:
95  if self.bson_only_mode:
96  if self.recv_bson() == None:
97  break
98  continue
99 
100  # non-BSON handling
101  data = self.request.recv(cls.incoming_buffer)
102  # Exit on empty string
103  if data.strip() == '':
104  break
105  elif len(data.strip()) > 0:
106  self.protocol.incoming(data.strip(''))
107  else:
108  pass
109  except Exception as e:
110  pass
111  self.protocol.log("debug", "socket connection timed out! (ignore warning if client is only listening..)")
112 
113  def finish(self):
114  """
115  Called when TCP connection finishes
116  """
117  cls = self.__class__
118  cls.clients_connected -= 1
119  self.protocol.finish()
120  if cls.client_count_pub:
121  cls.client_count_pub.publish(cls.clients_connected)
122  self.protocol.log("info", "disconnected. " + str(cls.clients_connected) + " client total." )
123 
124  def send_message(self, message=None):
125  """
126  Callback from rosbridge
127  """
128  self.request.sendall(message)


rosbridge_server
Author(s): Jonathan Mace
autogenerated on Wed Jun 3 2020 03:55:18