-
Notifications
You must be signed in to change notification settings - Fork 24
Make DNSSD queries cancellable #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
610463d
a6299e5
de2fd16
8be4b7d
472d5c0
6ad9bd9
8102fb4
792d8e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,21 +110,6 @@ struct DNSSD { | |
let recordStream = AsyncThrowingStream<ReplyHandler.Record, Error> { continuation in | ||
let handler = QueryReplyHandler(handler: replyHandler, continuation) | ||
|
||
// Wrap `handler` into a pointer so we can pass it to DNSServiceQueryRecord | ||
let handlerPointer = UnsafeMutableRawPointer.allocate( | ||
byteCount: MemoryLayout<QueryReplyHandler>.stride, | ||
alignment: MemoryLayout<QueryReplyHandler>.alignment | ||
) | ||
|
||
handlerPointer.initializeMemory(as: QueryReplyHandler.self, repeating: handler, count: 1) | ||
|
||
// The handler might be called multiple times so don't deallocate inside `callback` | ||
defer { | ||
let pointer = handlerPointer.assumingMemoryBound(to: QueryReplyHandler.self) | ||
pointer.deinitialize(count: 1) | ||
pointer.deallocate() | ||
} | ||
|
||
// This is called once per record received | ||
let callback: DNSServiceQueryRecordReply = { _, _, _, errorCode, _, _, _, rdlen, rdata, _, context in | ||
guard let handlerPointer = context else { | ||
|
@@ -138,32 +123,54 @@ struct DNSSD { | |
handler.handleRecord(errorCode: errorCode, data: rdata, length: rdlen) | ||
} | ||
|
||
let serviceRefPtr = UnsafeMutablePointer<DNSServiceRef?>.allocate(capacity: 1) | ||
defer { serviceRefPtr.deallocate() } | ||
let serviceRefPointer = UnsafeMutablePointer<DNSServiceRef?>.allocate(capacity: 1) | ||
|
||
// Wrap 'handler' into a pointer so we can pass it to DNSServiceQueryRecord | ||
let replyHandlerPointer = UnsafeMutablePointer<QueryReplyHandler>.allocate(capacity: 1) | ||
replyHandlerPointer.initialize(to: handler) | ||
|
||
// Run the query | ||
let _code = DNSServiceQueryRecord( | ||
serviceRefPtr, | ||
serviceRefPointer, | ||
kDNSServiceFlagsTimeout, | ||
0, | ||
name, | ||
UInt16(type.kDNSServiceType), | ||
UInt16(kDNSServiceClass_IN), | ||
callback, | ||
handlerPointer | ||
replyHandlerPointer | ||
) | ||
|
||
// Check if query completed successfully | ||
guard _code == kDNSServiceErr_NoError else { | ||
DNSSD.deallocatePointers(serviceRefPointer: serviceRefPointer, replyHandlerPointer: replyHandlerPointer) | ||
return continuation.finish(throwing: AsyncDNSResolver.Error(dnssdCode: _code)) | ||
} | ||
|
||
// Read reply from the socket (blocking) then call reply handler | ||
DNSServiceProcessResult(serviceRefPtr.pointee) | ||
DNSServiceRefDeallocate(serviceRefPtr.pointee) | ||
let serviceSockFD = DNSServiceRefSockFD(serviceRefPointer.pointee) | ||
guard serviceSockFD != -1 else { | ||
DNSSD.deallocatePointers(serviceRefPointer: serviceRefPointer, replyHandlerPointer: replyHandlerPointer) | ||
return continuation.finish(throwing: AsyncDNSResolver.Error(code: .internalError, message: "Failed to access the DNSSD service socket")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aren't we leaking the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed the code so that the deallocates are also called in this branch and the other error branch just above. |
||
} | ||
|
||
let readSource = DispatchSource.makeReadSource(fileDescriptor: serviceSockFD) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be passing our own queue here rather than using the default? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isn't this file descriptor leaked? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I close it now in the cancellation handler There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you'll need DispatchSources that use file descriptors and don't use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, thanks for the feedback! I implemented it in the latest commit |
||
readSource.setEventHandler { | ||
// Read reply from the socket (blocking) then call reply handler | ||
DNSServiceProcessResult(serviceRefPointer.pointee) | ||
|
||
readSource.cancel() | ||
continuation.finish() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should cancel the read source There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Applied in latest commit |
||
} | ||
|
||
readSource.setCancelHandler { | ||
DNSSD.deallocatePointers(serviceRefPointer: serviceRefPointer, replyHandlerPointer: replyHandlerPointer) | ||
close(serviceSockFD) | ||
} | ||
readSource.resume() | ||
|
||
// Streaming done | ||
continuation.finish() | ||
continuation.onTermination = { _ in | ||
readSource.cancel() | ||
} | ||
} | ||
|
||
// Build reply using records received | ||
|
@@ -173,6 +180,12 @@ struct DNSSD { | |
|
||
return try replyHandler.generateReply(records: records) | ||
} | ||
|
||
private static func deallocatePointers(serviceRefPointer: UnsafeMutablePointer<DNSServiceRef?>, replyHandlerPointer: UnsafeMutablePointer<DNSSD.QueryReplyHandler>) { | ||
DNSServiceRefDeallocate(serviceRefPointer.pointee) | ||
serviceRefPointer.deallocate() | ||
replyHandlerPointer.deallocate() | ||
} | ||
} | ||
|
||
// MARK: - dnssd query reply handler | ||
|
Uh oh!
There was an error while loading. Please reload this page.