@@ -28,6 +28,7 @@ type State = {
2828 pair : Pair
2929 stop : ( ) => void
3030 seen : Map < string , number >
31+ parent : Map < string , string | undefined >
3132 gc : number
3233}
3334
@@ -77,6 +78,60 @@ function serverID(input: { relayURL: string; relaySecret: string }) {
7778 return createHash ( "sha256" ) . update ( `${ input . relayURL } |${ input . relaySecret } ` ) . digest ( "hex" ) . slice ( 0 , 16 )
7879}
7980
81+ function recordSession ( event : Event ) {
82+ if ( ! obj ( event . properties ) ) return
83+ const next = state
84+ if ( ! next ) return
85+
86+ if ( event . type !== "session.created" && event . type !== "session.updated" && event . type !== "session.deleted" ) {
87+ return
88+ }
89+
90+ const info = obj ( event . properties . info ) ? event . properties . info : undefined
91+ const id = str ( info ?. id )
92+ if ( ! id ) return
93+
94+ if ( event . type === "session.deleted" ) {
95+ next . parent . delete ( id )
96+ return
97+ }
98+
99+ next . parent . set ( id , str ( info ?. parentID ) )
100+ }
101+
102+ function routeSession ( sessionID : string ) {
103+ const next = state
104+ if ( ! next ) {
105+ return {
106+ sessionID,
107+ subagent : false ,
108+ }
109+ }
110+
111+ const visited = new Set < string > ( )
112+ let current = sessionID
113+ let target = sessionID
114+ let subagent = false
115+
116+ while ( true ) {
117+ if ( visited . has ( current ) ) break
118+ visited . add ( current )
119+
120+ if ( ! next . parent . has ( current ) ) break
121+ const parentID = next . parent . get ( current )
122+ if ( ! parentID ) break
123+
124+ subagent = true
125+ target = parentID
126+ current = parentID
127+ }
128+
129+ return {
130+ sessionID : target ,
131+ subagent,
132+ }
133+ }
134+
80135/**
81136 * Classify an IPv4 address into a reachability tier.
82137 * Lower number = more likely reachable from an external/overlay network device.
@@ -167,17 +222,21 @@ function list(hostname: string, port: number, advertised: string[] = []) {
167222}
168223
169224function map ( event : Event ) : { type : Type ; sessionID : string } | undefined {
225+ recordSession ( event )
226+
170227 if ( ! obj ( event . properties ) ) return
171228
172229 if ( event . type === "permission.asked" ) {
173230 const sessionID = str ( event . properties . sessionID )
174231 if ( ! sessionID ) return
175- return { type : "permission" , sessionID }
232+ const route = routeSession ( sessionID )
233+ return { type : "permission" , sessionID : route . sessionID }
176234 }
177235
178236 if ( event . type === "session.error" ) {
179237 const sessionID = str ( event . properties . sessionID )
180238 if ( ! sessionID ) return
239+ if ( routeSession ( sessionID ) . subagent ) return
181240 if ( ! shouldNotifyError ( event . properties . error ) ) return
182241 return { type : "error" , sessionID }
183242 }
@@ -187,6 +246,7 @@ function map(event: Event): { type: Type; sessionID: string } | undefined {
187246 if ( ! sessionID ) return
188247 if ( ! obj ( event . properties . status ) ) return
189248 if ( event . properties . status . type !== "idle" ) return
249+ if ( routeSession ( sessionID ) . subagent ) return
190250 return { type : "complete" , sessionID }
191251}
192252
@@ -405,6 +465,7 @@ export namespace PushRelay {
405465 pair,
406466 stop : unsub ,
407467 seen : new Map ( ) ,
468+ parent : new Map ( ) ,
408469 gc : 0 ,
409470 }
410471
0 commit comments