"""Own bounded proxy-route model; no SIP socket or configuration changes."""
import json
def trace(route,start,destination,budget):
    if isinstance(budget,bool) or not isinstance(budget,int) or not 0<=budget<=255:raise ValueError('budget integer 0..255 required')
    node=start;rows=[]
    while True:
        if node==destination:return {'status':'delivered_to_authored_destination','visits':rows+[{'node':node,'received_budget':budget,'action':'destination'}]}
        if budget==0:return {'status':'483_in_model','visits':rows+[{'node':node,'received_budget':0,'action':'reject_without_forwarding'}]}
        if node not in route:return {'status':'route_missing_in_model','visits':rows+[{'node':node,'received_budget':budget,'action':'no_authored_next_hop'}]}
        rows.append({'node':node,'received_budget':budget,'action':'forward','next':route[node],'sent_budget':budget-1})
        node=route[node];budget-=1
def demo():
    cycle=trace({'A':'B','B':'C','C':'B'},'A','D',5)
    short=trace({'A':'B','B':'C','C':'D'},'A','D',1)
    good=trace({'A':'B','B':'C','C':'D'},'A','D',3)
    assert cycle['status']==short['status']=='483_in_model' and good['status']=='delivered_to_authored_destination'
    assert len(cycle['visits'])==6 and [x['node'] for x in cycle['visits']]==['A','B','C','B','C','B']
    assert all(r['sent_budget']==r['received_budget']-1 for out in [cycle,short,good] for r in out['visits'] if r['action']=='forward')
    rejects=0
    for budget in [-1,256,True,1.5]:
        try:trace({},'A','D',budget)
        except ValueError:rejects+=1
        else:raise AssertionError(budget)
    return {'loop_route':cycle,'acyclic_budget_too_short':short,'acyclic_sufficient_budget':good,'invalid_budget_cases_rejected':rejects,'483_alone_proves_loop':False,'actual_SIP_or_provider_or_PBX_executed':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=False,indent=2))
