@@ -95,17 +95,21 @@ export class Browser extends EventEmitter {
9595 } )
9696 }
9797
98+ const receiveTime = Date . now ( )
99+
98100 Object . keys ( nameMap ) . forEach ( function ( name ) {
99101 // unregister all services shutting down
100102 self . goodbyes ( name , packet ) . forEach ( self . removeService . bind ( self ) )
101103
102104 // register all new services
103- var matches = self . buildServicesFor ( name , packet , self . txt , rinfo )
105+ var matches = self . buildServicesFor ( name , packet , self . txt , rinfo , receiveTime )
104106 if ( matches . length === 0 ) return
105107
106108 matches . forEach ( ( service : Service ) => {
107- if ( self . serviceMap [ service . fqdn ] ) {
108- self . updateService ( service )
109+ const existingService = self . _services . find ( ( s ) => dnsEqual ( s . fqdn , service . fqdn ) )
110+ if ( existingService ) {
111+ existingService . lastSeen = service . lastSeen
112+ self . updateService ( existingService , service )
109113 return
110114 }
111115 self . addService ( service )
@@ -128,6 +132,20 @@ export class Browser extends EventEmitter {
128132 this . mdns . query ( this . name , 'PTR' )
129133 }
130134
135+ public expire ( ) {
136+ const currentTime = Date . now ( )
137+
138+ this . _services = this . _services . filter ( ( service ) => {
139+ if ( ! service . ttl || service . lastSeen === undefined ) return true // No expiry
140+ const expireTime = service . lastSeen + service . ttl * 1000
141+ if ( expireTime < currentTime ) {
142+ this . emit ( 'down' , service )
143+ return false
144+ }
145+ return true
146+ } )
147+ }
148+
131149 public get services ( ) {
132150 return this . _services ;
133151 }
@@ -140,9 +158,9 @@ export class Browser extends EventEmitter {
140158 this . emit ( 'up' , service )
141159 }
142160
143- private updateService ( service : Service ) {
161+ private updateService ( existingService : Service , service : Service ) {
144162 // check if txt updated
145- if ( equalTxt ( service . txt , this . _services . find ( ( s ) => dnsEqual ( s . fqdn , service . fqdn ) ) ? .txt || { } ) ) return
163+ if ( equalTxt ( service . txt , existingService . txt || { } ) ) return
146164 // if the new service is not allowed by the txt query, remove it
147165 if ( ! filterService ( service , this . txtQuery ) ) {
148166 this . removeService ( service . fqdn )
@@ -194,15 +212,17 @@ export class Browser extends EventEmitter {
194212 // https://tools.ietf.org/html/rfc6763#section-7.1
195213 // Selective Instance Enumeration (Subtypes)
196214 //
197- private buildServicesFor ( name : string , packet : any , txt : KeyValue , referer : any ) {
215+ private buildServicesFor ( name : string , packet : any , txt : KeyValue , referer : any , receiveTime : number ) {
198216 var records = packet . answers . concat ( packet . additionals ) . filter ( ( rr : ServiceRecord ) => rr . ttl > 0 ) // ignore goodbye messages
199217
200218 return records
201219 . filter ( ( rr : ServiceRecord ) => rr . type === 'PTR' && dnsEqual ( rr . name , name ) )
202220 . map ( ( ptr : ServiceRecord ) => {
203221 const service : KeyValue = {
204222 addresses : [ ] ,
205- subtypes : [ ]
223+ subtypes : [ ] ,
224+ ttl : ptr . ttl ,
225+ lastSeen : receiveTime
206226 }
207227
208228 records . filter ( ( rr : ServiceRecord ) => {
0 commit comments