Skip to content

Commit

Permalink
Merge pull request #10 from DataDog/CIAPP-571-Fix-network-instrumenta…
Browse files Browse the repository at this point in the history
…tion-fails

CIAPP-571 Network instrumentation fails with some methods
If using a method with a nil completion, it could crash and delegate was not being properly called.
  • Loading branch information
Ignacio Bonafonte authored Nov 20, 2020
2 parents c0acac8 + 058243c commit 0b03aa7
Showing 1 changed file with 30 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -178,21 +178,29 @@ class DDNetworkInstrumentation {
}
var originalIMP: IMP?
let sessionTaskId = UUID().uuidString

let block: @convention(block) (URLSession, AnyObject, @escaping (Any?, URLResponse?, Error?) -> Void) -> URLSessionTask = { session, argument, completion in

let block: @convention(block) (URLSession, AnyObject, ((Any?, URLResponse?, Error?) -> Void)? ) -> URLSessionTask = { session, argument, completion in

if let url = argument as? URL,
self.injectHeaders == true {
let request = URLRequest(url: url)

if selector == #selector(URLSession.dataTask(with:completionHandler:) as (URLSession) -> (URL, @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask) {
return session.dataTask(with: request, completionHandler: completion)
if let completion = completion {
return session.dataTask(with: request, completionHandler: completion)
} else {
return session.dataTask(with: request)
}
} else {
return session.downloadTask(with: request, completionHandler: completion)
if let completion = completion {
return session.downloadTask(with: request, completionHandler: completion)
} else {
return session.downloadTask(with: request)
}
}
}

let castedIMP = unsafeBitCast(originalIMP, to: (@convention(c) (URLSession, Selector, Any, @escaping (Any?, URLResponse?, Error?) -> Void) -> URLSessionDataTask).self)
var task: URLSessionTask
let castedIMP = unsafeBitCast(originalIMP, to: (@convention(c) (URLSession, Selector, Any, ( (Any?, URLResponse?, Error?) -> Void)?) -> URLSessionDataTask).self)
var task: URLSessionTask!

var completionBlock = completion
if objc_getAssociatedObject(argument, &idKey) == nil {
Expand All @@ -205,7 +213,11 @@ class DDNetworkInstrumentation {
DDNetworkActivityLogger.log(response: response, dataOrFile: object, sessionTaskId: sessionTaskId)
}
}
completion(object, response, error)
if let completion = completion {
completion(object, response, error)
} else {
(session.delegate as? URLSessionTaskDelegate)?.urlSession?(session, task: task, didCompleteWithError: error)
}
}
completionBlock = completionWrapper
}
Expand Down Expand Up @@ -243,10 +255,11 @@ class DDNetworkInstrumentation {
var originalIMP: IMP?
let sessionTaskId = UUID().uuidString

let block: @convention(block) (URLSession, URLRequest, AnyObject, @escaping (Any?, URLResponse?, Error?) -> Void) -> URLSessionTask = { session, request, argument, completion in

let castedIMP = unsafeBitCast(originalIMP, to: (@convention(c) (URLSession, Selector, URLRequest, AnyObject, @escaping (Any?, URLResponse?, Error?) -> Void) -> URLSessionDataTask).self)
let block: @convention(block) (URLSession, URLRequest, AnyObject, ( (Any?, URLResponse?, Error?) -> Void)?) -> URLSessionTask = { session, request, argument, completion in

let castedIMP = unsafeBitCast(originalIMP, to: (@convention(c) (URLSession, Selector, URLRequest, AnyObject, ( (Any?, URLResponse?, Error?) -> Void)?) -> URLSessionDataTask).self)

var task: URLSessionTask!
var completionBlock = completion
if objc_getAssociatedObject(argument, &idKey) == nil {
let completionWrapper: (Any?, URLResponse?, Error?) -> Void = { object, response, error in
Expand All @@ -258,13 +271,17 @@ class DDNetworkInstrumentation {
DDNetworkActivityLogger.log(response: response, dataOrFile: object, sessionTaskId: sessionTaskId)
}
}
completion(object, response, error)
if let completion = completion {
completion(object, response, error)
} else {
(session.delegate as? URLSessionTaskDelegate)?.urlSession?(session, task: task, didCompleteWithError: error)
}
}
completionBlock = completionWrapper
}

let instrumentedRequest = self.instrumentedRequest(for: request)
let task = castedIMP(session, selector, instrumentedRequest, argument, completionBlock)
task = castedIMP(session, selector, instrumentedRequest, argument, completionBlock)
DDNetworkActivityLogger.log(request: instrumentedRequest, sessionTaskId: sessionTaskId)

self.setIdKey(value: sessionTaskId, for: task)
Expand Down

0 comments on commit 0b03aa7

Please sign in to comment.