+def route(packet, saddr, daddr):
+ print('TRACE ', saddr, daddr, packet)
+ try: client = clients[daddr]
+ except KeyError: dclient = None
+ if dclient is not None:
+ dclient.queue_outbound(packet)
+ elif daddr == c.server or daddr not in c.network:
+ print('TRACE INBOUND ', saddr, daddr, packet)
+ queue_inbound(packet)
+ elif daddr == relay:
+ log_discard(packet, saddr, daddr, 'relay')
+ else:
+ log_discard(packet, saddr, daddr, 'no client')
+
+#---------- client ----------
+
+class Client():
+ def __init__(self, ip, cs, pw):
+ # instance data members
+ self._ip = ip
+ self._cs = cs
+ self.pw = pw
+ self._rq = collections.deque() # requests
+ # self._pq = PacketQueue(...)
+ # plus from config:
+ # .max_batch_down
+ # .max_queue_time
+ # .max_request_time
+ # .target_requests_outstanding
+
+ if ip not in c.network:
+ raise ValueError('client %s not in network' % ip)
+
+ for k in ('max_batch_down','max_queue_time','max_request_time',
+ 'target_requests_outstanding'):
+ req = cfg.getint(cs, k)
+ limit = cfg.getint('limits',k)
+ self.__dict__[k] = min(req, limit)
+
+ self._pq = PacketQueue(self.max_queue_time)
+
+ if ip in clients:
+ raise ValueError('multiple client cfg sections for %s' % ip)
+ clients[ip] = self
+
+ def process_arriving_data(self, d):
+ for packet in slip.decode(d):
+ (saddr, daddr) = packet_addrs(packet)
+ if saddr != self._ip:
+ raise ValueError('wrong source address %s' % saddr)
+ route(packet, saddr, daddr)
+
+ def _req_cancel(self, request):
+ request.finish()
+
+ def _req_error(self, err, request):
+ self._req_cancel(request)
+
+ def queue_outbound(self, packet):
+ self._pq.append(packet)
+ self._check_outbound()
+
+ def http_request(self, request):
+ request.setHeader('Content-Type','application/octet-stream')
+ reactor.callLater(self.max_request_time, self._req_cancel, request)
+ request.notifyFinish().addErrback(self._req_error, request)
+ self._rq.append(request)
+ self._check_outbound()
+
+ def _check_outbound(self):
+ while True:
+ try: request = self._rq[0]
+ except IndexError: request = None
+ if request and request.finished:
+ self._rq.popleft()
+ continue