class Rtp_proxy_client_udp(object): pending_requests = None is_local = False worker = None bind_address = None global_config = None def __init__(self, global_config, address, bind_address = None, nworkers = None): self.address = address self.is_local = False if nworkers == None: self.worker = Udp_server(global_config, bind_address, \ self.process_reply, flags = 0) else: self.worker = Udp_server(global_config, bind_address, \ self.process_reply, flags = 0, nworkers = nworkers) self.pending_requests = {} self.bind_address = bind_address self.global_config = global_config def send_command(self, command, result_callback = None, *callback_parameters): cookie = md5(str(random()) + str(time())).hexdigest() command = '%s %s' % (cookie, command) timer = Timeout(self.retransmit, 1, -1, cookie) self.pending_requests[cookie] = [3, timer, command, result_callback, callback_parameters] self.worker.send_to(command, self.address) def retransmit(self, cookie): triesleft, timer, command, result_callback, callback_parameters = self.pending_requests[cookie] if triesleft == 0: timer.cancel() del self.pending_requests[cookie] self.go_offline() if result_callback != None: result_callback(None, *callback_parameters) return self.worker.send_to(command, self.address) self.pending_requests[cookie][0] -= 1 def process_reply(self, data, address, worker): cookie, result = data.split(None, 1) parameters = self.pending_requests.pop(cookie, None) if parameters == None: return parameters[1].cancel() if parameters[3] != None: parameters[3](result.strip(), *parameters[4]) def reconnect(self, address, bind_address = None): self.address = address if bind_address != self.bind_address: self.worker.shutdown() self.worker = Udp_server(self.global_config, bind_address, \ self.process_reply, flags = 0) self.bind_address = bind_address def shutdown(self): self.worker.shutdown() self.worker = None
class Rtp_proxy_client_udp(object): pending_requests = None is_local = False worker = None bind_address = None global_config = None def __init__(self, global_config, address, bind_address=None): self.address = address self.is_local = False self.worker = Udp_server(global_config, bind_address, \ self.process_reply, flags = 0) self.pending_requests = {} self.bind_address = bind_address self.global_config = global_config def send_command(self, command, result_callback=None, *callback_parameters): cookie = md5(str(random()) + str(time())).hexdigest() command = '%s %s' % (cookie, command) timer = Timeout(self.retransmit, 1, -1, cookie) self.pending_requests[cookie] = [ 3, timer, command, result_callback, callback_parameters ] self.worker.send_to(command, self.address) def retransmit(self, cookie): triesleft, timer, command, result_callback, callback_parameters = self.pending_requests[ cookie] if triesleft == 0: timer.cancel() del self.pending_requests[cookie] self.go_offline() if result_callback != None: result_callback(None, *callback_parameters) return self.worker.send_to(command, self.address) self.pending_requests[cookie][0] -= 1 def process_reply(self, data, address, worker): cookie, result = data.split(None, 1) parameters = self.pending_requests.pop(cookie, None) if parameters == None: return parameters[1].cancel() if parameters[3] != None: parameters[3](result.strip(), *parameters[4]) def reconnect(self, address, bind_address=None): self.address = address if bind_address != self.bind_address: self.worker.shutdown() self.worker = Udp_server(self.global_config, bind_address, \ self.process_reply, flags = 0) self.bind_address = bind_address
class Rtp_proxy_client_udp(object): pending_requests = None is_local = False worker = None uopts = None global_config = None delay_flt = None def __init__(self, global_config, address, bind_address=None, family=None, nworkers=None): self.address = address self.is_local = False self.uopts = Udp_server_opts(bind_address, self.process_reply, family) self.uopts.flags = 0 ##self.uopts.ploss_in_rate = 0.025 ##self.uopts.pdelay_out_max = 1.0 if nworkers != None: self.uopts.nworkers = nworkers self.worker = Udp_server(global_config, self.uopts) self.pending_requests = {} self.global_config = global_config self.delay_flt = recfilter(0.95, 0.025) def send_command(self, command, result_callback=None, *callback_parameters): cookie = md5(str(random()) + str(time())).hexdigest() next_retr = self.delay_flt.lastval * 4.0 rtime = 3.0 if isinstance(command, Rtp_proxy_cmd): if command.type == 'I': rtime = 10.0 if command.type == 'G': rtime = 1.0 nretr = command.nretr command = str(command) else: if command.startswith('I'): rtime = 10.0 elif command.startswith('G'): rtime = 1.0 nretr = None if nretr == None: nretr = getnretrans(next_retr, rtime) command = '%s %s' % (cookie, command) timer = Timeout(self.retransmit, next_retr, 1, cookie) stime = MonoTime() self.worker.send_to(command, self.address) nretr -= 1 self.pending_requests[cookie] = (next_retr, nretr, timer, command, result_callback, stime, callback_parameters) def retransmit(self, cookie): next_retr, triesleft, timer, command, result_callback, stime, callback_parameters = self.pending_requests[ cookie] #print 'command to %s timeout %s cookie %s triesleft %d' % (str(self.address), command, cookie, triesleft) if triesleft <= 0 or self.worker == None: del self.pending_requests[cookie] self.go_offline() if result_callback != None: result_callback(None, *callback_parameters) return #next_retr *= 2 timer = Timeout(self.retransmit, next_retr, 1, cookie) stime = MonoTime() self.worker.send_to(command, self.address) triesleft -= 1 self.pending_requests[cookie] = (next_retr, triesleft, timer, command, result_callback, stime, callback_parameters) def process_reply(self, data, address, worker, rtime): try: cookie, result = data.split(None, 1) except: print('Rtp_proxy_client_udp.process_reply(): invalid response %s' % data) return parameters = self.pending_requests.pop(cookie, None) if parameters == None: return next_retr, triesleft, timer, command, result_callback, stime, callback_parameters = parameters timer.cancel() if result_callback != None: result_callback(result.strip(), *callback_parameters) ##self.delay_flt.apply(rtime - stime) #print 'Rtp_proxy_client_udp.process_reply(): delay %f' % (rtime - stime) def reconnect(self, address, bind_address=None): self.address = address if bind_address != self.uopts.laddress: self.uopts.laddress = bind_address self.worker.shutdown() self.worker = Udp_server(self.global_config, self.uopts) self.delay_flt = recfilter(0.95, 0.25) def shutdown(self): self.worker.shutdown() self.worker = None def get_rtpc_delay(self): return self.delay_flt.lastval
class Rtp_proxy_client_udp(object): pending_requests = None is_local = False worker = None uopts = None global_config = None delay_flt = None def __init__(self, global_config, address, bind_address = None, family = None, nworkers = None): self.address = address self.is_local = False self.uopts = Udp_server_opts(bind_address, self.process_reply, family) self.uopts.flags = 0 ##self.uopts.ploss_in_rate = 0.025 ##self.uopts.pdelay_out_max = 1.0 if nworkers != None: self.uopts.nworkers = nworkers self.worker = Udp_server(global_config, self.uopts) self.pending_requests = {} self.global_config = global_config self.delay_flt = recfilter(0.95, 0.025) def send_command(self, command, result_callback = None, *callback_parameters): cookie = md5(str(random()) + str(time())).hexdigest() next_retr = self.delay_flt.lastval * 4.0 rtime = 3.0 if isinstance(command, Rtp_proxy_cmd): if command.type == 'I': rtime = 10.0 if command.type == 'G': rtime = 1.0 nretr = command.nretr command = str(command) else: if command.startswith('I'): rtime = 10.0 elif command.startswith('G'): rtime = 1.0 nretr = None if nretr == None: nretr = getnretrans(next_retr, rtime) command = '%s %s' % (cookie, command) timer = Timeout(self.retransmit, next_retr, 1, cookie) stime = MonoTime() self.worker.send_to(command, self.address) nretr -= 1 self.pending_requests[cookie] = (next_retr, nretr, timer, command, result_callback, stime, callback_parameters) def retransmit(self, cookie): next_retr, triesleft, timer, command, result_callback, stime, callback_parameters = self.pending_requests[cookie] #print 'command to %s timeout %s cookie %s triesleft %d' % (str(self.address), command, cookie, triesleft) if triesleft <= 0 or self.worker == None: del self.pending_requests[cookie] self.go_offline() if result_callback != None: result_callback(None, *callback_parameters) return #next_retr *= 2 timer = Timeout(self.retransmit, next_retr, 1, cookie) stime = MonoTime() self.worker.send_to(command, self.address) triesleft -= 1 self.pending_requests[cookie] = (next_retr, triesleft, timer, command, result_callback, stime, callback_parameters) def process_reply(self, data, address, worker, rtime): try: cookie, result = data.split(None, 1) except: print('Rtp_proxy_client_udp.process_reply(): invalid response %s' % data) return parameters = self.pending_requests.pop(cookie, None) if parameters == None: return next_retr, triesleft, timer, command, result_callback, stime, callback_parameters = parameters timer.cancel() if result_callback != None: result_callback(result.strip(), *callback_parameters) ##self.delay_flt.apply(rtime - stime) #print 'Rtp_proxy_client_udp.process_reply(): delay %f' % (rtime - stime) def reconnect(self, address, bind_address = None): self.address = address if bind_address != self.uopts.laddress: self.uopts.laddress = bind_address self.worker.shutdown() self.worker = Udp_server(self.global_config, self.uopts) self.delay_flt = recfilter(0.95, 0.25) def shutdown(self): self.worker.shutdown() self.worker = None def get_rtpc_delay(self): return self.delay_flt.lastval
class Rtp_proxy_client_udp(Rtp_proxy_client_net): pending_requests = None is_local = False worker = None uopts = None global_config = None delay_flt = None ploss_out_rate = 0.0 pdelay_out_max = 0.0 sock_type = SOCK_DGRAM def __init__(self, global_config, address, bind_address=None, family=AF_INET, nworkers=None): # print('Rtp_proxy_client_udp(family=%s)' % family) self.address = self.getdestbyaddr(address, family) self.is_local = False self.uopts = Udp_server_opts(bind_address, self.process_reply, family) self.uopts.flags = 0 self.uopts.ploss_out_rate = self.ploss_out_rate self.uopts.pdelay_out_max = self.pdelay_out_max if nworkers != None: self.uopts.nworkers = nworkers self.worker = Udp_server(global_config, self.uopts) self.pending_requests = {} self.global_config = global_config self.delay_flt = recfilter(0.95, 0.25) def send_command(self, command, result_callback=None, *callback_parameters): entropy = str(random()) + str(time()) cookie = md5(entropy.encode()).hexdigest() next_retr = self.delay_flt.lastval * 4.0 exp_time = 3.0 if isinstance(command, Rtp_proxy_cmd): if command.type == 'I': exp_time = 10.0 if command.type == 'G': exp_time = 1.0 nretr = command.nretr command = str(command) else: if command.startswith('I'): exp_time = 10.0 elif command.startswith('G'): exp_time = 1.0 nretr = None if nretr == None: nretr = getnretrans(next_retr, exp_time) command = '%s %s' % (cookie, command) timer = Timeout(self.retransmit, next_retr, 1, cookie) preq = Rtp_proxy_pending_req(next_retr, nretr - 1, timer, command, \ result_callback, callback_parameters) self.worker.send_to(command, self.address) self.pending_requests[cookie] = preq def retransmit(self, cookie): preq = self.pending_requests[cookie] # print('command to %s timeout %s cookie %s triesleft %d' % (str(self.address), preq.command, cookie, preq.triesleft)) if preq.triesleft <= 0 or self.worker == None: del self.pending_requests[cookie] self.go_offline() if preq.result_callback != None: preq.result_callback(None, *preq.callback_parameters) return preq.retransmits += 1 preq.next_retr *= 2 preq.timer = Timeout(self.retransmit, preq.next_retr, 1, cookie) self.worker.send_to(preq.command, self.address) preq.triesleft -= 1 def go_offline(self): # To be replaced in the upper level class pass def process_reply(self, data, address, worker, rtime): try: cookie, result = data.split(None, 1) except: print('Rtp_proxy_client_udp.process_reply(): invalid response from %s: "%s"' % \ (str(address), data)) return preq = self.pending_requests.pop(cookie, None) if preq == None: return preq.timer.cancel() if rtime <= preq.stime: # MonoTime as the name suggests is supposed to be monotonic, # so if we get response earlier than request went out something # is very wrong. Fail immediately. rtime_fix = MonoTime() raise AssertionError('cookie=%s: MonoTime stale/went' \ ' backwards (%f <= %f, now=%f)' % (cookie, rtime.monot, \ preq.stime.monot, rtime_fix.monot)) if preq.result_callback != None: preq.result_callback(result.strip(), *preq.callback_parameters) # When we had to do retransmit it is not possible to figure out whether # or not this reply is related to the original request or one of the # retransmits. Therefore, using it to estimate delay could easily produce # bogus value that is too low or even negative if we cook up retransmit # while the original response is already in the queue waiting to be # processed. This should not be a big issue since UDP command channel does # not work very well if the packet loss goes to more than 30-40%. if preq.retransmits == 0: self.delay_flt.apply(rtime - preq.stime) # print('Rtp_proxy_client_udp.process_reply(): delay %f' % (rtime - preq.stime)) def reconnect(self, address, bind_address=None): # print('reconnect', address) address = self.getdestbyaddr(address, self.uopts.family) self.rtpp_class._reconnect(self, address, bind_address) def _reconnect(self, address, bind_address=None): self.address = address if bind_address != self.uopts.laddress: self.uopts.laddress = bind_address self.worker.shutdown() self.worker = Udp_server(self.global_config, self.uopts) self.delay_flt = recfilter(0.95, 0.25) def shutdown(self): self.worker.shutdown() self.worker = None def get_rtpc_delay(self): return self.delay_flt.lastval
class Rtp_proxy_client_udp(object): pending_requests = None is_local = False worker = None uopts = None global_config = None delay_flt = None ploss_out_rate = 0.0 pdelay_out_max = 0.0 def __init__(self, global_config, address, bind_address = None, family = None, nworkers = None): self.address = address self.is_local = False self.uopts = Udp_server_opts(bind_address, self.process_reply, family) self.uopts.flags = 0 self.uopts.ploss_out_rate = self.ploss_out_rate self.uopts.pdelay_out_max = self.pdelay_out_max if nworkers != None: self.uopts.nworkers = nworkers self.worker = Udp_server(global_config, self.uopts) self.pending_requests = {} self.global_config = global_config self.delay_flt = recfilter(0.95, 0.25) def send_command(self, command, result_callback = None, *callback_parameters): cookie = md5(str(random()) + str(time())).hexdigest() next_retr = self.delay_flt.lastval * 4.0 exp_time = 3.0 if isinstance(command, Rtp_proxy_cmd): if command.type == 'I': exp_time = 10.0 if command.type == 'G': exp_time = 1.0 nretr = command.nretr command = str(command) else: if command.startswith('I'): exp_time = 10.0 elif command.startswith('G'): exp_time = 1.0 nretr = None if nretr == None: nretr = getnretrans(next_retr, exp_time) command = '%s %s' % (cookie, command) timer = Timeout(self.retransmit, next_retr, 1, cookie) preq = Rtp_proxy_pending_req(next_retr, nretr - 1, timer, command, \ result_callback, callback_parameters) self.worker.send_to(command, self.address) self.pending_requests[cookie] = preq def retransmit(self, cookie): preq = self.pending_requests[cookie] #print 'command to %s timeout %s cookie %s triesleft %d' % (str(self.address), preq.command, cookie, preq.triesleft) if preq.triesleft <= 0 or self.worker == None: del self.pending_requests[cookie] self.go_offline() if preq.result_callback != None: preq.result_callback(None, *preq.callback_parameters) return preq.retransmits += 1 preq.next_retr *= 2 preq.timer = Timeout(self.retransmit, preq.next_retr, 1, cookie) self.worker.send_to(preq.command, self.address) preq.triesleft -= 1 def go_offline(self): # To be replaced in the upper level class pass def process_reply(self, data, address, worker, rtime): try: cookie, result = data.split(None, 1) except: print('Rtp_proxy_client_udp.process_reply(): invalid response from %s: "%s"' % \ (str(address), data)) return preq = self.pending_requests.pop(cookie, None) if preq == None: return preq.timer.cancel() if rtime <= preq.stime: # MonoTime as the name suggests is supposed to be monotonic, # so if we get response earlier than request went out something # is very wrong. Fail immediately. rtime_fix = MonoTime() raise AssertionError('cookie=%s: MonoTime stale/went' \ ' backwards (%f <= %f, now=%f)' % (cookie, rtime.monot, \ preq.stime.monot, rtime_fix.monot)) if preq.result_callback != None: preq.result_callback(result.strip(), *preq.callback_parameters) # When we had to do retransmit it is not possible to figure out whether # or not this reply is related to the original request or one of the # retransmits. Therefore, using it to estimate delay could easily produce # bogus value that is too low or even negative if we cook up retransmit # while the original response is already in the queue waiting to be # processed. This should not be a big issue since UDP command channel does # not work very well if the packet loss goes to more than 30-40%. if preq.retransmits == 0: self.delay_flt.apply(rtime - preq.stime) #print 'Rtp_proxy_client_udp.process_reply(): delay %f' % (rtime - preq.stime) def reconnect(self, address, bind_address = None): self.address = address if bind_address != self.uopts.laddress: self.uopts.laddress = bind_address self.worker.shutdown() self.worker = Udp_server(self.global_config, self.uopts) self.delay_flt = recfilter(0.95, 0.25) def shutdown(self): self.worker.shutdown() self.worker = None def get_rtpc_delay(self): return self.delay_flt.lastval
class Rtp_proxy_client_udp(object): udp_server = None pending_requests = None address = None online = False copy_supported = False stat_supported = False tnot_supported = False sbind_supported = False shutdown = False proxy_address = None caps_done = False is_local = False def __init__(self, global_config, address): self.udp_server = Udp_server(None, self.process_reply) self.pending_requests = {} self.address = address self.proxy_address = address[0] self.heartbeat() def send_command(self, command, result_callback = None, *callback_parameters): cookie = md5(str(random()) + str(time())).hexdigest() command = '%s %s' % (cookie, command) timer = Timeout(self.retransmit, 1, -1, cookie) self.pending_requests[cookie] = [3, timer, command, result_callback, callback_parameters] self.udp_server.send_to(command, self.address) def retransmit(self, cookie): triesleft, timer, command, result_callback, callback_parameters = self.pending_requests[cookie] if triesleft == 0: timer.cancel() del self.pending_requests[cookie] self.online = False if result_callback != None: result_callback(None, *callback_parameters) return self.udp_server.send_to(command, self.address) self.pending_requests[cookie][0] -= 1 def process_reply(self, data, address, udp_server): cookie, result = data.split(None, 1) parameters = self.pending_requests.pop(cookie, None) if parameters == None: return parameters[1].cancel() if parameters[3] != None: parameters[3](result.strip(), *parameters[4]) def caps_query1(self, result): if self.shutdown: self.udp_server.shutdown() return if result != '1': if result != None: self.copy_supported = False self.stat_supported = False self.tnot_supported = False self.sbind_supported = False self.caps_done = True Timeout(self.heartbeat, 60) return self.copy_supported = True self.send_command('VF 20080403', self.caps_query2) def caps_query2(self, result): if self.shutdown: self.udp_server.shutdown() return if result != None: if result == '1': self.stat_supported = True self.send_command('VF 20081224', self.caps_query3) return else: self.stat_supported = False self.tnot_supported = False self.sbind_supported = False self.caps_done = True Timeout(self.heartbeat, 60) def caps_query3(self, result): if self.shutdown: self.udp_server.shutdown() return if result != None: if result == '1': self.tnot_supported = True self.send_command('VF 20090810', self.caps_query4) return else: self.tnot_supported = False self.sbind_supported = False self.caps_done = True Timeout(self.heartbeat, 60) def caps_query4(self, result): if self.shutdown: self.udp_server.shutdown() return if result != None: if result == '1': self.sbind_supported = True else: self.sbind_supported = False self.caps_done = True Timeout(self.heartbeat, 60) def heartbeat(self): self.send_command('V', self.heartbeat_reply) def heartbeat_reply(self, version): if self.shutdown: self.udp_server.shutdown() return if version == '20040107': self.online = True if not self.caps_done: self.send_command('VF 20071218', self.caps_query1) return else: self.online = False Timeout(self.heartbeat, 60)