What does "error in connection_block_invoke_2: Connection interrupted" mean? - ios

Problem
I recently updated my iPhone to iOS 10.3.1 and Xcode to Version 8.3.2. Currently, I have an app which runs a few URLRequests once my app launches.
However, after updating both iOS and Xcode, the app occasionally return an error message:
error in connection_block_invoke_2: Connection interrupted
The message is quite vague but I assumed it has something to do with the URLRequests since it mentions "Connection interrupted".
Whenever this error message appears, it will "freeze" the app for ~5s before getting the data from the server.
Question
So, what does this error message actually mean? And how can I minimise it or fix it?
Example of one URLRequest:
func checkLogin () {
let username = txtUsername.text!
let password = txtPassword.text!
let post = "username=\(username)&password=\(password)"
NSLog("PostData: %#",post);
let url:URL = URL(string:"https://example.com/login.php")!
let postData = post.data(using: .utf8)!
let postLength = String( postData.count )
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = postData
request.setValue(postLength as String, forHTTPHeaderField: "Content-Length")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
return
}
if let jsonData = (try? JSONSerialization.jsonObject(with: data!, options: [])) as? [String:Any] {
let success = jsonData["success"] as! Int
if success == 1 {
//do something,
}
else {
//show alert
}
}
})
task.resume()
}
Duplicates
The following questions does not solve my problem as:
What is "error in __connection_block_invoke_2: Connection interrupted" in iOS?
I didn't receive any memory warning so the answer does not apply.
iOS: error in __connection_block_invoke_2: Connection interrupted
I didn't use AVCaptureMovieFileOutput and AVCaptureVideoDataOutput at all in my app, thus the answer also doesn't apply.
error in __connection_block_invoke_2: Connection interrupted on iPad & Xcode 7 error message "error in __connection_block_invoke_2: Connection interrupted" when app runs on iPad
No answer at all.

Related

IOS/SWIFT4 - HTTP load failed (error code: -1005 [4:-4])

Does anybody know what HTTP load failed (error code: -1005 [4:-4]) is? I saw a few answers on here, some say it's that the server can't process more than x requests at a time, others say its alamofire.
My script refreshes every 60 seconds and there is only one request at a time. I have alamofire installed in my project, but not using it for this refresh.
It works the first few times, but after a few minutes i get this 1005 error and then it never again afterwards unless i go to a different page and come back.
URLCache.shared.removeAllCachedResponses()
if let requestURL = URL(string: "https://www.example.com/file.php") {
var urlRequest = URLRequest(url: requestURL)
urlRequest.httpMethod = "POST"
let postString = "username=\(Username.text!)&password=\(Password.text!)&device_token=\(device_token)"
urlRequest.httpBody = postString.data(using: .utf8)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest as URLRequest) { (data, response, error) in
if let data = data {
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] {
// get lots of vars here
// Async Stuff
DispatchQueue.main.async(execute: {
// do lots of things here
})
}
} catch {
print("Error: \(error)")
}
}
}
task.resume()
}
The error goes like this:
TIC Read Status [2:0x60400016bac0]: 1:57
... HTTP load failed (error code: -1005 [4:-4])
... finished with error - code: -1005
• I tried to add session.reset(completionHandler: { print("session ended") }) at the end
• In another post i read that i should add a header-length. but not sure if i should do that on the server or the Xcode project?
• And somehow i can't catch this error and trigger something else.

Make iOS device as source client using Icecast

I want to make iOS device as source client to send the audio to icecast server. I have setup the icecast server on localhost successfully. Right now when I send below request to server it creates the mountpoint but only for first 8 sec of the audio, the total length of audio is 25 sec. I know this is because I'm not sending the data in chunks. Below is my request:
let requestString = "http://localhost:8000/"
let url = URL(string: requestString)
let mountPointName = "myMountPoint"
var request = URLRequest(url: url!)
request.httpMethod = "SOURCE /\(mountPointName) ICE/1.0"
request.addValue("SOURCE /mp3test ICE/1.0", forHTTPHeaderField: "SOURCE")
request.addValue("audio/ogg", forHTTPHeaderField: "Content-Type")
request.setValue("Basic c291cmNlOmhhY2ttZQ==", forHTTPHeaderField: "Authorization")
request.setValue("Server name", forHTTPHeaderField: "ice-name")
request.setValue("https://www.google.com", forHTTPHeaderField: "ice-url")
request.setValue("RockTest", forHTTPHeaderField: "ice-genre")
request.setValue("128", forHTTPHeaderField: "ice-bitrate")
request.setValue("0", forHTTPHeaderField: "ice-private")
request.setValue("1", forHTTPHeaderField: "ice-public")
request.setValue("Server description", forHTTPHeaderField: "ice-description")
request.setValue("samplerate=44100;bitrate=128;channels=2", forHTTPHeaderField: "ice-audio-info")
self.recurseivelySendRequest(request)
My recursive function:
func recurseivelySendRequest(_ _request: URLRequest) {
var request = _request
do {
let fileURL = Bundle.main.url(forResource: "mount", withExtension: "ogg") let data = try Data(contentsOf: fileURL!)
let inputStream = InputStream(data: data)
request.httpBodyStream = inputStream
} catch let error {
print(error)
}
// let dataTask = URLSession.shared.uploadTask(withStreamedRequest: request)
// dataTask.resume()
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
if (error != nil) {
print(error ?? "error = unknown")
return
}
print(response ?? "response = unknown")
do {
let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)
print(json)
} catch let error {
print(error)
let str = String.init(data: data!, encoding: String.Encoding.utf8)
print(str ?? "str = nil")
}
self.recurseivelySendRequest(request)
}
dataTask.resume()
}
The problem with above code is it sends only few part of the audio also If I don't send the request recursively the mountpoint no longer exists and seems it is replacing the data not adding. So what I want is to create the mountpoint once and then write the audio data in chunks.
I also followed Icecast 2: protocol description, streaming to it using
I was on wrong path finally I found iOS-Icecast-Client on github. It helps me to make a connection with icecast-server and send the recorder audio to server in chunks. As I have already mentioned that I was able to setup the icecast-server on localhost.
After downloading the above library in AudioProcessor.m file there is a line
ShoutOutputStream_Init("192.x.x.x", 8000, "/stream", "source", "hackme", 0);
Where 192.x.x.x is your wifi ip as you can not use localhost in device to connect it. Also make sure your system and device should be on same wifi connection to reach the network.
8000 is your port defined in icecast.xml.
/stream is mount point name defined in icecast.xml.
And here comes where I spent few hours to get the username and password these are also defined in authentication tag in icecast.xml. I used the default one source and hackme.
0 is whether it is vorbis (0) or a .mp3 (1) file.
Finally I got it working. And Many thanks to gstream79 to provide us such a wonderful library.

Getting Error While making rest call in swift 3 for iOS 10

let url string = "https://myURL"
func task(_ urlstring: String,json: AnyObject, ComplitionHandler: #escaping taskCompletionHandler )
{
do
{
let jsonData = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
let url = URL(string: urlstring)
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.httpBody = jsonData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request, completionHandler: {(data,response,error) in
if(error != nil)
{
print(error)
ComplitionHandler(nil, nil )
return
}
ComplitionHandler(data!, response!)
})
task.resume()
}
catch
{
print("error")
}
}
I have done some Changes in .plist by adding
(App Transport Security ,Allow Arbitrary Loads=YES,Allow Arbitrary Loads in Web Content=YES).
But Still getting below error:
NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://myurl, NSErrorFailingURLStringKey=https://myurl, NSErrorClientCertificateStateKey=0
Well the list of trusted root certificates is updated on iOS 10, so judging on that you should make sure that your SSL Certificate is not part of iOS 10 blocked root certificates.
Updated List
If you have a WoSign CA Free SSL Certificate G2, Apple is blocking it, as they are claiming that is has multiple control failures. More info here

Calling WCF (on Azure) from Swift 2.0 fails with status code 400

Trying to invoke a WCF service hosted on Azure, fails with HTTP error 400. The Web service in essence is acting as my Braintree (mobile payments) server side of things.
Here's the relevant code:
let soapEnvelope = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Header><Action s:mustUnderstand=\"1\" xmlns=\"http://schemas.microsoft.com/ws/2005/05/addressing/none\">http://tempuri.org/IService1/GenerateToken</Action></s:Header><s:Body><GenerateToken xmlns=\"http://tempuri.org/\" /></s:Body></s:Envelope>"
let soapEnvelopeLength = String(soapEnvelope.characters.count)
let clientTokenURL = NSURL(string: "http://xxx.xxx.net/Service1.svc")
let clientTokenRequest = NSMutableURLRequest(URL: clientTokenURL!)
let session = NSURLSession.sharedSession()
clientTokenRequest.HTTPMethod = "POST"
clientTokenRequest.HTTPBody = soapEnvelope.dataUsingEncoding(NSUTF8StringEncoding)
clientTokenRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
clientTokenRequest.addValue(soapEnvelopeLength, forHTTPHeaderField: "Content-Length")
clientTokenRequest.addValue("http://tempuri.org/IService1/GenerateToken", forHTTPHeaderField: "soapAction")
let task = session.dataTaskWithRequest(clientTokenRequest, completionHandler: {data, response, error -> Void in
print(response)
let clientToken = String(data: data!, encoding: NSUTF8StringEncoding)
let brainTree = Braintree(clientToken: clientToken!)
if error != nil {
print(error)
}
})
task.resume()
Failure occurs on:
let task = session.dataTaskWithRequest(clientTokenRequest, completionHandler: {data, response, error -> Void in
My soapEnvelope is pretty much a copy/paste of the auto-generated XML from WCF Test Client tool.
I also tried with the following soapEnvelope, but still getting a 400. As a result clientToken remains nil and BTree is never initialised:
let soapEnvelope = "<?xml version=\"1.0\" encoding=\"utf-8\"><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><GenerateToken xmlns=\"http://tempuri.org/\" /></s:Body></s:Envelope>"
Any ideas?
Thanks,
Polis
To answer my own question after monitoring traffic with Fiddler, I had to change SOAP envelope to:
let soapEnvelope = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><GenerateToken xmlns=\"http://tempuri.org/\" /></s:Body></s:Envelope>"
This worked.

Swift to php on local server doesn't work on my device?

I am having an issue with the following code, it works on the iphone 5s simulator. But when i attach my iphone5s device it doesn't work. With the simulator i get this (as expected) back from swiftupload.php
Button pressed <- swift
responseString = Optional({"message":"some variable"}Success) <- from php
Email has ben sent <- swift
And with my device attached i get
Button pressed
responseString = Optional()
The php file looks like:
$postdata = json_decode(file_get_contents("php://input"), TRUE);
$message = $postdata["data"];
// Store values in an array
$returnValue = array("message" => $message);
// Send back request in JSON format
echo json_encode($returnValue);
And this is the function in swift
func postToServerFunction(){
// json php
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost/mydomain.com/swiftupload.php")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
let params = ["data":"some variable"] as Dictionary<String, String>
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(params, options: [])
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
//Response print
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
if let HTTPResponse = response as? NSHTTPURLResponse {
let statusCode = HTTPResponse.statusCode
if statusCode == 200{
print("Email has ben sent")
}
}
})
task.resume()
print("Button pressed")
}
On the iPhone the localhost is IP of the iPhone.
Replace "localhost" with IP of your MAC/PC and check App Transport Security exceptions https://stackoverflow.com/a/30732693/4755417

Resources